class_docstr: To allow the paralleled env workers consume a single DataQueue until it's exhausted.
  
  See `tianshou issue #322 <https://github.com/thu-ml/tianshou/issues/322>`_.
  
  The requirement is to make every possible seed (stored in :class:`qlib.rl.utils.DataQueue` in our case)
  consumed by exactly one environment. This is not possible by tianshou's native VectorEnv and Collector,
  because tianshou is unaware of this "exactly one" constraint, and might launch extra workers.
  
  Consider a corner case, where concurrency is 2, but there is only one seed in DataQueue.
  The reset of two workers must be both called according to the logic in collect.
  The returned results of two workers are collected, regardless of what they are.
  The problem is, one of the reset result must be invalid, or repeated,
  because there's only one need in queue, and collector isn't aware of such situation.
  
  Luckily, we can hack the vector env, and make a protocol between single env and vector env.
  The single environment (should be :class:`qlib.rl.utils.EnvWrapper` in our case) is responsible for
  reading from queue, and generate a special observation when the queue is exhausted. The special obs
  is called "nan observation", because simply using none causes problems in shared-memory vector env.
  :class:`FiniteVectorEnv` then read the observations from all workers, and select those non-nan
  observation. It also maintains an ``_alive_env_ids`` to track which workers should never be
  called again. When also the environments are exhausted, it will raise StopIteration exception.
  
  The usage of this vector env in collector are two parts:
  
  1. If the data queue is finite (usually when inference), collector should collect "infinity" number of
     episodes, until the vector env exhausts by itself.
  2. If the data queue is infinite (usually in training), collector can set number of episodes / steps.
     In this case, data would be randomly ordered, and some repetitions wouldn't matter.
  
  One extra function of this vector env is that it has a logger that explicitly collects logs
  from child workers. See :class:`qlib.rl.utils.LogWriter`.
code: def _get_default_rew(self) -> Any:
      return copy.deepcopy(self._default_rew)
  
imports: from __future__ import annotations
  import copy
  import warnings
  from contextlib import contextmanager
  from typing import Any, Callable, Dict, Generator, List, Optional, Set, Tuple, Type, Union, cast
  import gym
  import numpy
  from tianshou.env import BaseVectorEnv, DummyVectorEnv, ShmemVectorEnv, SubprocVectorEnv
  from qlib.typehint import Literal
  from .log import LogWriter
label_desc: Use image node_id 8 for calling the FiniteVectorEnv obj's underlying member method code with example usage: obj._get_default_rew() and returns: copy