class_docstr: An environment that interfaces with external agents.
  
  Unlike simulator envs, control is inverted: The environment queries the
  policy to obtain actions and in return logs observations and rewards for
  training. This is in contrast to gym.Env, where the algorithm drives the
  simulation through env.step() calls.
  
  You can use ExternalEnv as the backend for policy serving (by serving HTTP
  requests in the run loop), for ingesting offline logs data (by reading
  offline transitions in the run loop), or other custom use cases not easily
  expressed through gym.Env.
  
  ExternalEnv supports both on-policy actions (through self.get_action()),
  and off-policy actions (through self.log_action()).
  
  This env is thread-safe, but individual episodes must be executed serially.
  
  .. testcode::
      :skipif: True
  
      from ray.tune import register_env
      from ray.rllib.algorithms.dqn import DQN
      YourExternalEnv = ...
      register_env("my_env", lambda config: YourExternalEnv(config))
      algo = DQN(env="my_env")
      while True:
          print(algo.train())
class_docstr_tok: ["An","environment","that","interfaces","with","external","agents",".","Unlike","simulator","envs",",","control","is","inverted",":","The","environment","queries","the","policy","to","obtain","actions","and","in","return","logs","observations","and","rewards","for","training",".","This","is","in","contrast","to","gym.Env",",","where","the","algorithm","drives","the","simulation","through","env.step","(",")","calls",".","You","can","use","ExternalEnv","as","the","backend","for","policy","serving","(","by","serving","HTTP","requests","in","the","run","loop",")",",","for","ingesting","offline","logs","data","(","by","reading","offline","transitions","in","the","run","loop",")",",","or","other","custom","use","cases","not","easily","expressed","through","gym.Env",".","ExternalEnv","supports","both","on-policy","actions","(","through","self.get_action","(",")",")",",","and","off-policy","actions","(","through","self.log_action","(",")",")",".","This","env","is","thread-safe",",","but","individual","episodes","must","be","executed","serially",".","..","testcode",":",":",":","skipif",":","True","from","ray.tune","import","register_env","from","ray.rllib.algorithms.dqn","import","DQN","YourExternalEnv","=","...","register_env","(","``","my_env","''",",","lambda","config",":","YourExternalEnv","(","config",")",")","algo","=","DQN","(","env=","''","my_env","''",")","while","True",":","print","(","algo.train","(",")",")"]
docstr: Converts an RLlib MultiAgentEnv into a BaseEnv object.
  
  The resulting BaseEnv is always vectorized (contains n
  sub-environments) to support batched forward passes, where n may
  also be 1. BaseEnv also supports async execution via the `poll` and
  `send_actions` methods and thus supports external simulators.
  
  Args:
      make_env: A callable taking an int as input (which indicates
          the number of individual sub-environments within the final
          vectorized BaseEnv) and returning one individual
          sub-environment.
      num_envs: The number of sub-environments to create in the
          resulting (vectorized) BaseEnv. The already existing `env`
          will be one of the `num_envs`.
      remote_envs: Whether each sub-env should be a @ray.remote
          actor. You can set this behavior in your config via the
          `remote_worker_envs=True` option.
      remote_env_batch_wait_ms: The wait time (in ms) to poll remote
          sub-environments for, if applicable. Only used if
          `remote_envs` is True.
  
  Returns:
      The resulting BaseEnv object.
docstr_tok: ["Converts","an","RLlib","MultiAgentEnv","into","a","BaseEnv","object",".","The","resulting","BaseEnv","is","always","vectorized","(","contains","n","sub-environments",")","to","support","batched","forward","passes",",","where","n","may","also","be","1",".","BaseEnv","also","supports","async","execution","via","the","`","poll","`","and","`","send_actions","`","methods","and","thus","supports","external","simulators",".","Args",":","make_env",":","A","callable","taking","an","int","as","input","(","which","indicates","the","number","of","individual","sub-environments","within","the","final","vectorized","BaseEnv",")","and","returning","one","individual","sub-environment",".","num_envs",":","The","number","of","sub-environments","to","create","in","the","resulting","(","vectorized",")","BaseEnv",".","The","already","existing","`","env","`","will","be","one","of","the","`","num_envs","`",".","remote_envs",":","Whether","each","sub-env","should","be","a","@","ray.remote","actor",".","You","can","set","this","behavior","in","your","config","via","the","`","remote_worker_envs=True","`","option",".","remote_env_batch_wait_ms",":","The","wait","time","(","in","ms",")","to","poll","remote","sub-environments","for",",","if","applicable",".","Only","used","if","`","remote_envs","`","is","True",".","Returns",":","The","resulting","BaseEnv","object","."]
code: def to_base_env(
      self,
      make_env: Optional[Callable[[int], EnvType]] = None,
      num_envs: int = 1,
      remote_envs: bool = False,
      remote_env_batch_wait_ms: int = 0,
      restart_failed_sub_environments: bool = False,
  ) -> "BaseEnv":
      """Converts an RLlib MultiAgentEnv into a BaseEnv object.
  
      The resulting BaseEnv is always vectorized (contains n
      sub-environments) to support batched forward passes, where n may
      also be 1. BaseEnv also supports async execution via the `poll` and
      `send_actions` methods and thus supports external simulators.
  
      Args:
          make_env: A callable taking an int as input (which indicates
              the number of individual sub-environments within the final
              vectorized BaseEnv) and returning one individual
              sub-environment.
          num_envs: The number of sub-environments to create in the
              resulting (vectorized) BaseEnv. The already existing `env`
              will be one of the `num_envs`.
          remote_envs: Whether each sub-env should be a @ray.remote
              actor. You can set this behavior in your config via the
              `remote_worker_envs=True` option.
          remote_env_batch_wait_ms: The wait time (in ms) to poll remote
              sub-environments for, if applicable. Only used if
              `remote_envs` is True.
  
      Returns:
          The resulting BaseEnv object.
      """
      if num_envs != 1:
          raise ValueError(
              "External(MultiAgent)Env does not currently support "
              "num_envs > 1. One way of solving this would be to "
              "treat your Env as a MultiAgentEnv hosting only one "
              "type of agent but with several copies."
          )
      env = ExternalEnvWrapper(self)
  
      return env
  
imports: import gymnasium
  import queue
  import threading
  import uuid
  from typing import Callable, Tuple, Optional, TYPE_CHECKING
  from ray.rllib.env.base_env import BaseEnv
  from ray.rllib.utils.annotations import override, PublicAPI
  from ray.rllib.utils.typing import EnvActionType, EnvInfoDict, EnvObsType, EnvType, MultiEnvDict
  from ray.rllib.utils.deprecation import deprecation_warning
label_desc: Use image node_id 9 for calling the ExternalEnv obj's underlying member method code with example usage: obj.to_base_env(make_env, num_envs, remote_envs, remote_env_batch_wait_ms, restart_failed_sub_environments) and returns: env