Невозможно сослаться на импортированный модуль в __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
блоки, чтобы они не вызывали исключения - если выполнение кода там не критично, когда программа заканчивается.