2010-03-28 12 views
21

Jestem debugowania z konsoli Pythona i chciałbym przeładować moduł za każdym razem, gdy dokonam zmiany, więc nie muszę wyjść z konsoli i ponownie go wprowadzić. Robię:Właściwy sposób na przeładowanie modułu Pythona z konsoli

>>> from project.model.user import * 
>>> reload(user) 

ale otrzymują:

>>>NameError: name 'user' is not defined 

Co to jest właściwy sposób, aby przeładować całą klasę użytkownika? Czy istnieje lepszy sposób, aby to zrobić, być może automatyczne aktualizacje podczas debugowania?

Dzięki.

Odpowiedz

29

Gdy zapytałem, to najlepsze co możesz zrobić, to

>>> from project.models.user import * 
>>> import project # get module reference for reload 
>>> reload(project.models.user) # reload step 1 
>>> from project.models.user import * # reload step 2 

byłoby lepsze i czystsze jeśli użyto modułu obsługi bezpośrednio, zamiast robić import * (które prawie nigdy nie jest dobry sposób, żeby to zrobić) . Wtedy będzie to tylko

>>> from project.models import user 
>>> reload(user) 

To by było, co chcesz. Ale nie jest to bardzo miłe. Jeśli naprawdę potrzebujesz przeładowywać moduły tak często, muszę zapytać: dlaczego?

Moje podejrzenie (poparte wcześniejszymi doświadczeniami z ludźmi zadającymi podobne pytania) polega na tym, że testujesz swój moduł. Istnieje wiele sposobów na przetestowanie modułu, a zrobienie go ręcznie w Interaktywnym tłumaczu jest jednym z najgorszych sposobów. Zapisz jedną ze swoich sesji w pliku i użyj doctest, aby uzyskać szybką naprawę. Alternatywnie, zapisz go jako program i użyj python -i. Jednak jedynym świetnym rozwiązaniem jest użycie modułu unittest.

Jeśli to nie jest to, mam nadzieję, że jest coś lepszego, a nie gorszego. Naprawdę nie ma pożytku z reload (w rzeczywistości jest on usuwany w 3.x). To nie działa skutecznie - możesz przeładować moduł, ale pozostawić resztki z poprzednich wersji. Nie działa nawet na wszystkich rodzajach modułów - moduły rozszerzeń nie ładują się poprawnie, a czasem nawet przerażają po ponownym załadowaniu.

Kontekst korzystania z niego w interpretera interaktywnym nie pozostawia wiele do wyboru, co robisz i jakie jest najlepsze rozwiązanie.Poza tym, czasami ludzie używali reload() wdrożenie wtyczek itd Jest to niebezpieczne w najlepsze, a często można zrobić inaczej stosując albo exec (ah zło terytorium znajdujemy się w) lub segregowane proces.

+0

+1: Naprawdę nie ma dobrego wykorzystania przeładowania. –

+0

Co robię, aby znaleźć to pytanie, czy używam konsoli do eksploracji struktury danych importowanej z JSON. Chcę użyć "reload", aby zachować niektóre funkcje w moim edytorze tekstu, które przechodzą przez strukturę na różne sposoby, edytują je, a następnie ponownie uruchamiają, bez konieczności wychodzenia z konsoli. Mimo to, jeśli Python nie może tego obsługiwać w sposób czysty, z powodów związanych z implementacją, takich jak ta niezdolność do usunięcia "resztek", myślę, że muszę się mylić, aby chcieć to zrobić ;-p +1 dla odpowiedzi, która pozwala mi to zrobić, tak czy inaczej, chociaż. –

+0

+1 za pokazanie mi, że naprawdę powinienem pisać testy, zamiast robić rzeczy w interpretatorze ręcznie, nawet w celu precyzyjnego dostrojenia. Byłoby to również użyteczne w przyszłych testach bez regresji. –

4

Niestety musisz użyć:

>>> from project.model import user 
>>> reload(user) 

nie wiem od szczytu mojej głowie czegoś, co automatycznie przeładować modułów na interaktywnej wierszu ... Ale nie widzę żadnego powodu, nikt nie powinien istnieć (w rzeczywistości, to nie byłoby zbyt trudne do wykonania, albo ...)

teraz mógłby zrobić coś takiego:

from types import ModuleType 
import sys 
_reload_builtin = reload 
def reload(thing): 
    if isinstance(thing, ModuleType): 
     _reload_builtin(thing) 
    elif hasattr(thing, '__module__') and thing.__module__: 
     module = sys.modules[thing.__module__] 
     _reload_builtin(module) 
    else: 
     raise TypeError, "reload() argument must be a module or have an __module__" 
4

Nie można użyć funkcji reload() w skuteczny sposób.

Python nie zapewnia skutecznego wsparcia dla przeładowania lub rozładowania wcześniej zaimportowanych modułów ; Odwołania do modułów powodują, że ponowne załadowanie modułu jest niepraktyczne, ponieważ odniesienia mogą istnieć w wielu miejscach w programie.

Python 3 całkowicie usunął funkcję ponownego ładowania().

+1

To nie odwołania do modułów, które to robią: reload() faktycznie mutuje obiekt modułu. Jest to odwołanie do funkcji i klas wewnątrz modułu, które rozbijają rzeczy (w szczególności referencje generowane przez foo import *). –

+0

Tak, zgadzam się i możesz mieć inne moduły programu, które zaimportowały moduł, który chcesz zwolnić(). – systempuntoout

1

Dla python3, reload został przeniesiony do imp moduł. możesz użyć imp.reload(). Można odwołać się do this post.

>>> import imp 
>>> import project # get module reference for reload 
>>> imp.reload(project.models.user) # reload step 1 
>>> from project.models.user import * # reload step 2 
Powiązane problemy