Why I can't I set an attribute on an OpenAI Gym environment directly

Viewed 220

So I am running into an interesting bug when writing a custom OpenAI gym environment. The code below is the minimal environment I can write that reproduces the bug:

import gym

class TestEnv(gym.Env):
    obs = 3

    def set_obs(self, obs):
        self.obs = obs

    def reset(self):
        return self.obs

    def step(self, a):
        return self.obs, 0, False, None

gym.register('TestEnv-v0', 
             entry_point=f'{__name__}:TestEnv',
             max_episode_steps=1000)

env = gym.make('TestEnv-v0')
print(env.reset())
print(env.obs)
env.obs = 5
print(env.reset())
print(env.obs)
env.set_obs(8)
print(env.reset())
print(env.obs)
3
3
3
5
8
5

For some reason, there is a difference between calling set_obs and setting the obs attribute directly! I have never applied the pattern of a setter function in Python (it smells of Java too much), but here I have to use it so that the new obs is actually taken into account.

1 Answers

When you register an environment with gym.register and a max_episode_steps parameter, OpenAI Gym automatically wraps your environment into a TimeLimit object that will make sure that after max_episode_steps the environment returns done=True. Gym wrappers can forward function calls (i.e. set_obs) to the unwrapperd environment, but they don't forward attributes. So env.obs = 5 sets the obs attribute on an instance of TimeLimit instead of TestEnv instance

Related