1.render()无法弹出游戏窗口的原因
你使用的代码可能与你的gym版本不符

(图片来源网络,侵删)
在我目前的测试看来,gym 0.23的版本,在初始化env的时候只需要游戏名称这一个实参,然后在需要渲染的时候主动调用render()去渲染游戏窗口,比如:
env = gym.make("CartPole-v1") obs = env.reset() for _ in range(1000): env.render() obs, reward, done, info = env.step(env.action_space.sample()) # 以action随机抽样为例 if done: break env.close()
而在gym0.26的版本,在初始化env的时候你需要加入另一个实参:render_mode,如:

(图片来源网络,侵删)
env = gym.make("CartPole-v1", render_mode="human")
具体参数参考官方文档:https://www.gymlibrary.dev/
并且,你在reset时需要设置seed参数,并且还要用二项元组接收数据,而且step时需要用五项元组接收数据,否则会报错
就模仿官方文档的入门教程这样写:
import gym env = gym.make("LunarLander-v2", render_mode="human") observation, info = env.reset(seed=42) for _ in range(1000): action = policy(observation) # User-defined policy function observation, reward, terminated, truncated, info = env.step(action) if terminated or truncated: observation, info = env.reset() env.close()
2.在设置好 render_mode 后,调用reset()即会自动开始渲染
看了一下gym0.26的reset方法代码,它会根据你初始化env时传入的render_mode参数去决定它要不要渲染,并且,在gym0.26主动调用render是无效的
CartPole游戏的reset源码如下:
def reset( self, *, seed: Optional[int] = None, options: Optional[dict] = None, ): super().reset(seed=seed) # Note that if you use custom reset bounds, it may lead to out-of-bound # state/observations. low, high = utils.maybe_parse_reset_bounds( options, -0.05, 0.05 # default low ) # default high self.state = self.np_random.uniform(low=low, high=high, size=(4,)) self.steps_beyond_terminated = None if self.render_mode == "human": self.render() return np.array(self.state, dtype=np.float32), {}
可以看到,在最后,如果render_mode设置为"human",那么render方法将被调用。
3.在gym 0.26如何实现训练时不渲染,而测试时再渲染
在gym0.23版本,可以主动调用render来决定渲不渲染,而在gym0.26版本,只要reset就渲染,所以如果你刚开始就设定render_mode="human"的话,那么你将会看到整个训练过程,且动画渲染结束之后才会开始下一个episode的训练,所以训练时长会比不渲染时更长。
解决方案:
最初,我以为动态地去修改env.render_mode即可,但我发现env初始化之后这个就是一个无法修改的参数
所以,你可以在初始化训练的env_train时,不添加render_mode参数(或添加除human之外的参数),然后在测试的时候,新创建一个与之前一样的env:env_test
env_test = gym.make("CartPole-v1", render_mode='human')
用新的env_test去测试就好