2015-08-29 17 views
5

I zmodyfikowane sys.modules[__name__] do klasy Hello, tak:nie może znaleźć modułu czasu kiedy zmienił sys.modules [__ name__]

# hello.py 
import sys 
import time 

class Hello: 

    def print_time(self): 
     print 'hello, current time is:', time.time() 

sys.modules[__name__] = Hello() 

Potem importowane hello.py w innym pliku python test.py jak:

# test.py 
import hello 
hello.print_time() 

Ale otrzymałem komunikat o błędzie "AttributeError: 'NoneType' object has no attribute 'time'" po uruchomieniu python test.py. Wygląda na to, że hello.py nie może zaimportować modułu time.

naprawdę nie dowiedzieć się problem.

Jak mogę to naprawić?

+0

mam żadnego wytłumaczenia, dlaczego tak się dzieje i teraz jestem ciekawy też, ale go obejść można nadużywać zalegających zmieniając 'def print_time (self):' na 'def print_time (self, czas = czas): '. Przypominam, że była to zwykła sztuczka, zanim Python wspierał zakres leksykalny. – icktoofay

Odpowiedz

4

Ponieważ moduł time hello nie ma już żadnych odnośników wskazujących na to, został zbuforowany. Co oznacza, że ​​tracisz globale.

Nieco straszny dylemat: dołączyć go do klasy Hello.

import sys 

class Hello: 

    import time #Yes, the import statement in the class. 

    def print_time(self): 
     print 'hello, current time is:', time.time() 

sys.modules[__name__] = Hello() 
5

Okazuje się NightShadeQueen ma rację, że problemem jest to, że oryginalny moduł obiekt jest garbage zebrane, ale pytanie pozostaje, dlaczego to ma to zachowanie? Mianowicie, że wciąż ma zapis tego, co globalne zrobił istnieć-przedstawieniu coś, co było nigdy importowanego daje NameError, natomiast wszystko, co zrobiłistnieją obecnie None. Wkopałem się w źródło, żeby się przekonać.

Moduł to obiekt. Podobnie jak wiele obiektów, ma on __dict__, przechowujący wszystkie atrybuty, które nie mają jawnych szczelin. Podczas tworzenia obiektów globalnych są one dodawane do tego słownika.

Gdy funkcja jest tworzona, to utrzymuje referencję do słownika globals w momencie definicji. Nie zachowuje się w nim odniesienie do modułu, który jest właścicielem tego słownika - zachowuje jedynie odniesienie do samego słownika.

Z jakiegoś powodu, finalizator modułów czyści swój słownik. (Patrz the source.) Zamiast kasowania kluczy hurtowo, zastępuje je wszystkie None, komentarzem wyjaśniającym, że unika ponownego wprowadzania zmian w słowniku.

Szczerze mówiąc, nie widzę dlaczego finalizator moduł musi to zrobić; można rozsądnie po prostu usunąć jego odniesienie do słownika i pozwolić słownikowi radzić sobie z usuwaniem odniesień do jego wartości.

Powiązane problemy