2011-12-21 15 views
5

Używam obiektu __del__() wypisać ją ze zdarzenia (z wykorzystaniem schematu zdarzenie podobne do this):Nie można odwoływać się do importowanego modułu w __ __del()

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

dziwne otrzymałem następujący błąd przy koniec programu:

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

Jak to możliwe ?! my_environment to moduł, który zaimportowałem, jak to możliwe, że może to być Brak? (events jest globalnym obiektem w nim z hakami zdarzeń takich jak my_event)

+0

W jaki sposób zostanie to wywołane (poza zakończeniem programu)? Czy przewodnik zdarzeń nie miałby odniesienia do obiektu, który uniemożliwiłby gromadzenie śmieci? – interjay

+0

@interjay - Niektóre obiekty MyClass żyją podczas biegu, a niektóre są krótkotrwałe. Dodałem to wyczyszczenie zdarzenia dla późniejszego przypadku. – Jonathan

+1

Chodzi mi o to, że to nigdy nie będzie wywoływane dla obiektów krótkotrwałych, ponieważ obsługa zdarzeń ma do nich odniesienie. – interjay

Odpowiedz

7

Według python doc about __del__:

[...] inne globalne odwołuje metodą __del__() może już zostały usunięte lub w proces rozrywania (np. wyłączenie maszyn w celu importu). Z tego powodu, metody __del__() powinny stanowić absolutne minimum potrzebne do utrzymania zewnętrznych niezmienników.

Innymi słowy, gdy metoda __del__ nazywa na swoim obiekcie, my_enviroment mogły zostać „skasowany” przez pytona, więc może to być brak ...

3

Jeśli zaznaczysz dokumentacji Pythona, ty zauważy, że w momencie zakończenia obiektów, "maszyna" jest już zdemontowana. Oznacza to, że wiele z tego, na czym można polegać, już nie istnieje - w tym przypadku zmienna globalna z odniesieniem do modułu.

Co trzeba zrobić, to albo zapewnić swoich obiektów, które muszą mieć __del__ nazywane są niszczone przed zakończeniem programu - jeszcze lepiej, zrobić następnie menedżerów kontekście z __enter__ i __exit__ metod, a następnie użyć w ciągu with wypowiedzi. Lub po prostu zawijaj klauzule w __del__ w blokach try-except, aby nie powodowały wyjątków - jeśli wykonanie kodu nie jest krytyczne, gdy program się kończy.