简体   繁体   中英

Python program bombs out after finishing

I'm getting a strange Python error. I'm executing a file that looks like this.

if __name__ == '__main__':
    MyClass().main()
    print('Done 1')
    print('Done 2')

The preceding runs successfully. But when I change it to this, I get the strange result.

if __name__ == '__main__':
    myObject = MyClass()
    myObject.main()
    print('Done 1')
    print('Done 2')

The output looks like this.

Done 1
Done 2
Exception ignored in: <function Viewer.__del__ at 0x0000021569EF72F0> 
Traceback (most recent call last):
  File "C:\...\lib\site-packages\gym\envs\classic_control\rendering.py", line 143, in __del__
  File "C:\...\lib\site-packages\gym\envs\classic_control\rendering.py", line 62, in close
  File "C:\...\lib\site-packages\pyglet\window\win32\__init__.py", line 305, in close
  File "C:\...\lib\site-packages\pyglet\window\__init__.py", line 770, in close
ImportError: sys.meta_path is None, Python is likely shutting down

Process finished with exit code 0

There is a blank line after the final print line. The same thing happens when the final line does not have an end-of-line marker.

I get the same result whether I run it from within PyCharm using the run command or from the terminal.

As you can probably tell from the error lines, the program generates an animation. (It's the cart-pole problem from OpenAI gym.)

Since the program completes before the error, it's not a disaster. But I'd like to understand what's happening.

Thanks.

Python provides a __del__ dunder method for classes that will be called as the instances are garbage collected, if they're garbage collected .

When it's used, the __del__ method typically performs some sort of cleanup.

Due to the fact that it's fairly easy to inadvertently prevent an object from being collected, reliance on the __del__ to perform cleanup (instead of say, a context manager's __exit__ or an explicit .close() method) is generally advised against.

Your error highlights a different reason for avoiding relying on __del__ , however: that during shutdown __del__ will be called but possibly after other things that it relies on are freed .

The proposed workarounds on the github issue linked in the comments should be instructive, as they all ensure that the cleanup is done at a time where the things that that cleanup relies on (eg sys.meta_path ) are still in defined/not yet freed, eg:

try:
    del env
except ImportError:
    pass

and

env = gym.make('CartPole-v0')
...
env.env.close()

and (likely, but much less efficient or clear)

import gc; gc.collect()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM