Невозможно сослаться на импортированный модуль в __del__()

Я использую объект __del__() чтобы отписаться от события (используя схему событий, подобную этой):

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

Как ни странно, я получил следующую ошибку в конце выполнения программы:

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

Как это могло быть возможно?! my_environment модуль, который я импортировал, почему он может быть Нет? (events это глобальный объект в нем с перехватами событий, такими как my_event)

2 ответа

Решение

В соответствии с документом Python о__del__:

[...] другие глобалы, на которые ссылается __del__() Возможно, метод уже был удален или находится в процессе разрушения (например, отключение импортного оборудования). По этой причине, __del__() методы должны выполнять абсолютный минимум, необходимый для поддержки внешних инвариантов.

Другими словами, когда __del__ метод вызывается на вашем объекте, my_enviroment возможно, был "удален" python, так что это может быть None...

Если вы посмотрите документацию Python, то увидите, что когда объекты завершаются, в конце программы "механизм" уже разбирается. Это означает, что многое из того, на что вы бы положились, уже ушло - в данном случае это глобальная переменная со ссылкой на модуль.

Что вам нужно сделать, это либо обеспечить ваши объекты, которые должны иметь __del__ Вызываемые уничтожаются до завершения программы - еще лучше, сделайте тогда менеджеров контекста, с __enter__ а также __exit__ методы, а затем использовать в течение with заявления. Или просто оберните свои пункты в __del__ в try-except блоки, чтобы они не вызывали исключения - если выполнение кода там не критично, когда программа заканчивается.

Другие вопросы по тегам