2014-09-03 9 views
45

CPython ma dziwne zachowanie, w którym ustawia moduły na Brak podczas zamykania. To pomyłkowe rejestrowanie błędów podczas zamykania kodu wielowątkowości, który napisałem.Gdzie jest dokumentowana procedura zamykania Pythona?

Nie mogę znaleźć żadnej dokumentacji tego zachowania. To wspomniano mimochodem w PEP 432:

[...] znacznie zmniejszając liczbę modułów, które doświadczy „globalnych zestawie moduł do none” zachowanie, które jest używane do umyślnych cykle przerwy i próbę uwolnienia większej ilości środków zewnętrznych czysty.

Istnieją SO questions about this behaviour i C API documentation mentions shutdown behaviour for embedded interpreters.

Ja również znalazłem related thread on python-dev i related CPython bug:

Ta poprawka nie zmienia zachowanie modułu obiekty kasowanie ich globalnych słownik jak najszybciej są zwalniane.

Gdzie to zachowanie jest udokumentowane? Czy jest to specyficzne dla Pythona 2?

Odpowiedz

58

Zachowanie jest nie dobrze udokumentowane i jest obecny we wszystkich wersjach Pythonie 1,5-dosyć Python 3.4:

W ramach tej zmiany globalne modułu nie są już na siłę ustawiona do None podczas zamykania interpretera w większości przypadków, zamiast polegać na normalnej pracy cyklicznego odśmiecacza.

Jedyna dokumentacja dla zachowania jest moduleobject.c source code:

/* To make the execution order of destructors for global 
    objects a bit more predictable, we first zap all objects 
    whose name starts with a single underscore, before we clear 
    the entire dictionary. We zap them by replacing them with 
    None, rather than deleting them from the dictionary, to 
    avoid rehashing the dictionary (to some extent). */ 

Należy pamiętać, że ustawienie wartości None jest optymalizacja; Alternatywą byłoby usunięcie nazw z mapowania, które prowadziłyby do różnych błędów (wyjątków, a nie AttributeError s przy próbie użycia globali z obsługi __del__).

Jak dowiedziałeś się na liście mailingowej, zachowanie poprzedza cykliczny garbage collector; był to added in 1998, natomiast cyklicznym śmieciarzem był added in 2000. Ponieważ obiekty funkcyjne zawsze odwołują się do modułu, wszystkie obiekty funkcyjne w module dotyczą odwołań kołowych, dlatego konieczne było wyczyszczenie przed wprowadzeniem GC.

Został zachowany na miejscu nawet po dodaniu cyklicznego GC, ponieważ mogą występować obiekty o metodach związanych z cyklami. Te aren't otherwise garbage-collectable i czyszczenie słownika modułów spowodowałyby przynajmniej usunięcie modułu z takich cykli. W przeciwnym razie wszystkie globale tego modułu będą żyły.

Zmiany wprowadzone do PEP 442 zrobić teraz to możliwe dla śmieciarza, aby usunąć odwołania cykliczne z obiektami, które zapewniają __del__ finalizatora, eliminując potrzebę, aby wyczyścić moduł __dict__dla większości przypadków. Kod to still there, ale jest on wyzwalany tylko wtedy, gdy atrybut __dict__ jest wciąż aktywny, nawet po przeniesieniu zawartości sys.modules do słabych odniesień i uruchomieniu kolekcji GC podczas zamykania interpretera; moduł finalizatora modułów po prostu zmniejsza ich liczbę referencyjną.

0

Istnieje niewielka ilość odpowiedniej dokumentacji na bottom of the threading docs:

Po drugie, wszystkie próby przywozu muszą być zakończone przed rozpoczęciem interpreter zamykając się w dół. [..] Nieprzestrzeganie tego ograniczenia spowoduje sporadyczne wyjątki i awarie podczas zamykania interpretera (jako że późny import próbuje uzyskać dostęp do maszyn, które nie są już w ważnym stanie).