Source code for pettingzoo.utils.env_logger

from __future__ import annotations

import logging
from logging import Logger
from typing import Any

import gymnasium.spaces


[docs] class EnvLogger: """Used for logging warnings and errors for environments.""" mqueue: list[Any] = [] _output: bool = True
[docs] @staticmethod def get_logger() -> Logger: """Returns the logger object.""" logger = logging.getLogger(__name__) return logger
@staticmethod def _generic_warning(msg: Any) -> None: """Add a custom generic warning to the EnvLogger.""" logger = EnvLogger.get_logger() if not logger.hasHandlers(): handler = EnvWarningHandler(mqueue=EnvLogger.mqueue) logger.addHandler(handler) logger.warning(msg) # needed to get the pytest runner to work correctly, and doesn't seem to have serious issues EnvLogger.mqueue.append(msg)
[docs] @staticmethod def flush() -> None: """Flushes EnvLogger output.""" EnvLogger.mqueue.clear()
[docs] @staticmethod def suppress_output() -> None: """Suppresses EnvLogger output.""" EnvLogger._output = False
[docs] @staticmethod def unsuppress_output() -> None: """Resets EnvLogger output to be printed.""" EnvLogger._output = True
[docs] @staticmethod def error_possible_agents_attribute_missing(name: str) -> None: """Warns: ``[ERROR]: This environment does not support {attribute}.``.""" raise AttributeError( f"[ERROR]: This environment does not support {name}. This means that either the environment has procedurally generated agents such that this property cannot be well defined (which requires special learning code to handle) or the environment was improperly configured by the developer." )
[docs] @staticmethod def warn_action_out_of_bound( action: Any, action_space: gymnasium.spaces.Space, backup_policy: str ) -> None: """Warns: ``[WARNING]: Received an action {action} that was outside action space {action_space}.``.""" EnvLogger._generic_warning( f"[WARNING]: Received an action {action} that was outside action space {action_space}. Environment is {backup_policy}" )
[docs] @staticmethod def warn_on_illegal_move() -> None: """Warns: ``[WARNING]: Illegal move made, game terminating with current player losing.``.""" EnvLogger._generic_warning( "[WARNING]: Illegal move made, game terminating with current player losing. \nobs['action_mask'] contains a mask of all legal moves that can be chosen." )
[docs] @staticmethod def error_observe_before_reset() -> None: """Error: ``reset() needs to be called before observe.``.""" assert False, "reset() needs to be called before observe."
[docs] @staticmethod def error_step_before_reset() -> None: """Error: ``reset() needs to be called before step.``.""" assert False, "reset() needs to be called before step."
[docs] @staticmethod def warn_step_after_terminated_truncated() -> None: """Warns: ``[WARNING]: step() called after all agents are terminated or truncated. Should reset() first.``.""" EnvLogger._generic_warning( "[WARNING]: step() called after all agents are terminated or truncated. Should reset() first." )
[docs] @staticmethod def error_render_before_reset() -> None: """Error: ``reset() needs to be called before render.``.""" assert False, "reset() needs to be called before render."
[docs] @staticmethod def error_agent_iter_before_reset() -> None: """Error: ``reset() needs to be called before agent_iter().``.""" assert False, "reset() needs to be called before agent_iter()."
[docs] @staticmethod def error_nan_action() -> None: """Error: ``step() cannot take in a nan action.``.""" assert False, "step() cannot take in a nan action."
[docs] @staticmethod def error_state_before_reset() -> None: """Error: ``reset() needs to be called before state.``.""" assert False, "reset() needs to be called before state."
class EnvWarningHandler(logging.Handler): def __init__(self, *args, mqueue, **kwargs): logging.Handler.__init__(self, *args, **kwargs) self.mqueue = mqueue def emit(self, record: logging.LogRecord): m = self.format(record).rstrip("\n") self.mqueue.append(m) if EnvLogger._output: print(m)