class_docstr: Set of EnvRunners with n @ray.remote workers and zero or one local worker.
  
  Where: n >= 0.
class_docstr_tok: ["Set","of","EnvRunners","with","n","@","ray.remote","workers","and","zero","or","one","local","worker",".","Where",":","n",">","=","0","."]
docstr: Infer observation and action spaces from a remote worker.
  
  Returns:
      A dict mapping from policy ids to spaces.
docstr_tok: ["Infer","observation","and","action","spaces","from","a","remote","worker",".","Returns",":","A","dict","mapping","from","policy","ids","to","spaces","."]
code: def _get_spaces_from_remote_worker(self):
      """Infer observation and action spaces from a remote worker.
  
      Returns:
          A dict mapping from policy ids to spaces.
      """
      # Get ID of the first remote worker.
      worker_id = self.__worker_manager.actor_ids()[0]
  
      # Try to figure out spaces from the first remote worker.
      # Traditional RolloutWorker.
      if issubclass(self.env_runner_cls, RolloutWorker):
          remote_spaces = self.foreach_worker(
              lambda worker: worker.foreach_policy(
                  lambda p, pid: (
                      pid,
                      p.observation_space,
                      p.action_space,
                  )
              ),
              remote_worker_ids=[worker_id],
              local_worker=False,
          )
      # Generic EnvRunner.
      else:
          remote_spaces = self.foreach_worker(
              lambda worker: worker.marl_module.foreach_module(
                  lambda mid, m: (
                      mid,
                      m.config.observation_space,
                      m.config.action_space,
                  ),
              )
              if hasattr(worker, "marl_module")
              else [
                  (
                      DEFAULT_POLICY_ID,
                      worker.module.config.observation_space,
                      worker.module.config.action_space,
                  ),
              ]
          )
  
      if not remote_spaces:
          raise ValueError(
              "Could not get observation and action spaces from remote "
              "worker. Maybe specify them manually in the config?"
          )
      spaces = {
          e[0]: (getattr(e[1], "original_space", e[1]), e[2])
          for e in remote_spaces[0]
      }
  
      if issubclass(self.env_runner_cls, RolloutWorker):
          # Try to add the actual env's obs/action spaces.
          env_spaces = self.foreach_worker(
              lambda worker: worker.foreach_env(
                  lambda env: (env.observation_space, env.action_space)
              ),
              remote_worker_ids=[worker_id],
              local_worker=False,
          )
          if env_spaces:
              # env_spaces group spaces by environment then worker.
              # So need to unpack thing twice.
              spaces["__env__"] = env_spaces[0][0]
  
      logger.info(
          "Inferred observation/action spaces from remote "
          f"worker (local worker has no env): {spaces}"
      )
  
      return spaces
  
imports: import functools
  import gymnasium
  import logging
  import importlib.util
  import os
  from typing import Callable, Container, Dict, List, Optional, Tuple, Type, TYPE_CHECKING, TypeVar, Union
  import ray
  from ray.actor import ActorHandle
  from ray.exceptions import RayActorError
  from ray.rllib.core.rl_module.rl_module import SingleAgentRLModuleSpec
  from ray.rllib.evaluation.rollout_worker import RolloutWorker
  from ray.rllib.utils.actor_manager import RemoteCallResults
  from ray.rllib.env.base_env import BaseEnv
  from ray.rllib.env.env_context import EnvContext
  from ray.rllib.env.env_runner import EnvRunner
  from ray.rllib.offline import get_dataset_and_shards
  from ray.rllib.policy.policy import Policy, PolicyState
  from ray.rllib.policy.sample_batch import DEFAULT_POLICY_ID
  from ray.rllib.utils.actor_manager import FaultTolerantActorManager
  from ray.rllib.utils.annotations import DeveloperAPI
  from ray.rllib.utils.deprecation import Deprecated, deprecation_warning, DEPRECATED_VALUE
  from ray.rllib.utils.framework import try_import_tf
  from ray.rllib.utils.policy import validate_policy_id
  from ray.rllib.utils.typing import AgentID, EnvCreator, EnvType, EpisodeID, PartialAlgorithmConfigDict, PolicyID, SampleBatchType, TensorType
label_desc: Use image node_id 3 for calling the WorkerSet obj's underlying member method code with example usage: obj._get_spaces_from_remote_worker() and returns: spaces