I'm using an object's __del__() to unsubscribe it from an event (using an event scheme similar to this):

import my_enviroment
class MyClass():
    def __del__(self):
        my_environment.events.my_event -= self.event_handler_func

Oddly I received the following error at the end of the program's run:

Exception AttributeError: "'NoneType' object has no attribute 'events'" in <bound method MyClass.__del__ of <myclass.MyClass instance at 0x04C54580>> ignored

How could this be possible?! my_environment is a module I imported, how come it could be None? (events is a global object in it with event hooks such as my_event)

有帮助吗?

解决方案

According to the python doc about __del__ :

[...] other globals referenced by the __del__() method may already have been deleted or in the process of being torn down (e.g. the import machinery shutting down). For this reason, __del__() methods should do the absolute minimum needed to maintain external invariants.

In other words, when the __del__ method is called on your object, the my_enviroment may have been 'deleted' by python, so it can be None...

其他提示

If you check Python's documentation, you will see that at when objects are terminated, at the end of the program, the "machinery" is already being disassembled. That means that much of what you'd rely on is already gone - in this case, the global variable with a module reference.

What you have to do is to either ensure your objects that needs to have __del__ called are destroyed before the program ends - better yet, make then context managers, with __enter__ and __exit__ methods, and use then within with statements. Or just wrap you clauses in __del__ within try-except blocks so that they don't raise exceptions - if the execution of the code in there is not critical when the program is ending.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top