Jak przeładować moduły w powłoce django?


90

Pracuję z Django i cały czas używam powłoki Django. Irytujące jest to, że podczas gdy serwer Django przeładowuje się po zmianie kodu, powłoka nie ładuje się, więc za każdym razem, gdy zmieniam metodę, którą testuję, muszę zamknąć powłokę i ponownie ją zaimportować, ponownie zaimportować wszystkie moduły. potrzebuję, ponownie zainicjuj wszystkie potrzebne mi zmienne itp. Chociaż historia iPythona oszczędza wiele pisania na ten temat, nadal jest to uciążliwe. Czy istnieje sposób na automatyczne przeładowanie powłoki django, tak samo jak robi to serwer deweloperski django?

Wiem o reload (), ale importuję wiele modeli i ogólnie używam from app.models import *składni, więc reload () niewiele pomaga.


2
Powinieneś zaktualizować to pytanie, aby zaznaczyć poprawną odpowiedź „django-extensions”.
woodardj

1
Nie, dopóki to naprawdę nie zadziała. Mam zainstalowane rozszerzenia i żaden z moich kodów nie ładuje się automatycznie i nie widzę żadnej wzmianki o automatycznym przeładowywaniu w dokumentacji shell_plus. Wygląda na to, że w poleceniu runningerver_plus jest reloader, ale nie tego szukam.
Mad Wombat

Odpowiedzi:


37

Polecam używanie projektu django-extensions, jak wspomniano powyżej przez dongweiming. Ale zamiast tylko polecenia zarządzania „shell_plus”, użyj:

manage.py shell_plus --notebook

Spowoduje to otwarcie notatnika IPython w Twojej przeglądarce internetowej. Napisz swój kod w komórce, importuj itp. I uruchom go.

Gdy zmienisz moduły, po prostu kliknij pozycję menu notatnika „Jądro-> Uruchom ponownie”

Proszę bardzo, twój kod używa teraz zmodyfikowanych modułów.


30
„Po prostu użyj notatnika w Pythonie” nie jest odpowiedzią na pytanie OP.
J__

Ta metoda, chociaż nie jest automatyczna, jak% autoreload, działa bardziej niezawodnie niż autoreload. restart jądra gwarantuje, że wszystkie komórki w notebooku zostaną w pełni przeładowane. Dodatkowo możesz ponownie uruchomić i uruchomić wszystkie komórki, jeśli chcesz.
Anton I. Sipos

72

Sugerowałbym użycie rozszerzenia autoreload IPython .

./manage.py shell

In [1]: %load_ext autoreload
In [2]: %autoreload 2

Odtąd wszystkie zaimportowane moduły będą odświeżane przed oceną.

In [3]: from x import print_something
In [4]: print_something()
Out[4]: 'Something'

 # Do changes in print_something method in x.py file.

In [5]: print_something()
Out[5]: 'Something else'

Działa również, jeśli coś zostało zaimportowane przed %load_ext autoreloadpoleceniem.

./manage.py shell
In [1]: from x import print_something
In [2]: print_something()
Out[2]: 'Something'

 # Do changes in print_something method in x.py file.

In [3]: %load_ext autoreload
In [4]: %autoreload 2
In [5]: print_something()
Out[5]: 'Something else'

Możliwe jest również zapobieganie odświeżaniu niektórych importów za pomocą %aimportpoleceń i 3 strategii automatycznego przeładowania:

% autoreload

  • Odśwież wszystkie moduły (z wyjątkiem tych wykluczonych przez% aimport) teraz automatycznie.

% autoreload 0

  • Wyłącz automatyczne ponowne ładowanie.

% autoreload 1

  • Za każdym razem przeładowuj wszystkie moduły zaimportowane za pomocą% aimport przed wykonaniem wpisanego kodu Pythona.

% autoreload 2

  • Przeładuj wszystkie moduły (z wyjątkiem tych wykluczonych przez% aimport) za każdym razem przed wykonaniem wpisanego kodu Pythona.

% aimport

  • Lista modułów, które mają być importowane automatycznie lub nie.

% aimport foo

  • Zaimportuj moduł „foo” i oznacz go jako automatycznie przeładowywany dla% autoreload 1

% aimport -foo

  • Zaznacz moduł „foo”, aby nie był automatycznie ładowany.

Generalnie działa to dobrze dla mojego użytku, ale jest kilka błędów:

  • Zastępowanie obiektów kodu nie zawsze kończy się sukcesem: zmiana @property w klasie na zwykłą metodę lub metody na zmienną składową może powodować problemy (ale tylko w starych obiektach).
  • Funkcje, które są usuwane (np. Przez małpowanie) z modułu przed jego ponownym załadowaniem, nie są aktualizowane.
  • Modułów rozszerzeń C nie można ponownie ładować, więc nie można ich automatycznie przeładowywać.

3
W przypadku, gdy używasz django /manage.py shell_plus... jeśli wpiszesz %load_ext autoreloada następnie %autoreload 2, modele zostaną automatycznie przeładowane.
Fusion

Niesamowite, zrobiłeś mój dzień
Shamsul Arefin Sajib

Zwróć uwagę, że do tego potrzebny jest oczywiście ipython. Patrz np stackoverflow.com/a/47170195/50899
Rabarberski

38

spójrz na polecenie manage.py shell_plus udostępniane przez projekt django-extensions . Załaduje wszystkie pliki modelu podczas uruchamiania powłoki. i automatycznie przeładowuj dowolną modyfikację, ale nie potrzebujesz wyjścia, możesz tam bezpośrednio wywołać


40
Używam shell_plus i moje modele nie ładują się automatycznie, czy coś mi brakuje?
Diego Ponciano

30
shell_plus nie przeładowuje modeli, więc to nie odpowiada na pytanie.
aljabear

5
jak powiedziano, shell_plus nie przeładowuje modeli.
zenperttu

2
Może czegoś mi brakuje, ale shell_plus niczego dla mnie nie ładuje ponownie. Ładuje wszystkie modele podczas uruchamiania, co jest wygodne, ale to wszystko.
Mad Wombat

14
shell_plus MOŻE przeładować moduły za pomocą modułu automatycznego ładowania. Wpisz „% load_ext autoreload”, a następnie „% autoreload 2” - patrz ipython.org/ipython-doc/3/config/extensions/autoreload.html
bbrame

37

Moim rozwiązaniem jest napisanie kodu i zapisanie go do pliku, a następnie użycie:

python manage.py shell <test.py

Mogę więc wprowadzić zmianę, zapisać i ponownie uruchomić to polecenie, dopóki nie naprawię tego, co próbuję naprawić.


2
Ładnie i prosto. Jedna uwaga, dodaj exit()na dole pliku py, aby wyjść z powłoki Django w bardziej przejrzysty sposób. Dzięki.
Marc

Proste i eleganckie rozwiązanie. Dobra robota.
nikoskip

25

Wydaje się, że ogólny konsensus w tym temacie jest taki, że reload () w Pythonie jest do niczego i nie ma na to dobrego sposobu.


Błędny. Odpowiedź @ dongweiming powyżej jest rozwiązaniem i należy ją zaakceptować jako najlepszą.
Joseph Sheedy

3
Wiele komentarzy na temat jego odpowiedzi mówi, że shell_plus nie ładuje ponownie modeli
Mad Wombat

1
Właśnie go przetestowałem i nie ładuje się ponownie. Poza tym, co z kodem niemodelowym, który importuję ręcznie?
Mad Wombat

Klasy w aplikacji, której używam, ładują się teraz świetnie (Python 3.4.3, Django 1.9b1, django-extensions 1.5.9), w tym zwykły moduł inny niż django-model i klasa w nim. Minęło 5 lat od tej odpowiedzi i wiele się wydarzyło.
Joseph Sheedy

1
Wypróbowałem to na mojej konfiguracji 40 minut temu i shell_plus niczego dla mnie nie ładuje ponownie. Django 1.7.10, python 3.4.3, django-extensions 1.5.9.
Mad Wombat


5

Oto moje rozwiązanie tego niewygodnego rozwiązania. Używam IPython.

$ ./manage.py shell
> import myapp.models as mdls   # 'mdls' or whatever you want, but short...
> mdls.SomeModel.objects.get(pk=100)
> # At this point save some changes in the model
> reload(mdls)
> mdls.SomeModel.objects.get(pk=100)

W przypadku Pythona 3.x „reload” należy zaimportować za pomocą:

from importlib import reload

Mam nadzieję, że to pomoże. Oczywiście służy to do debugowania.

Twoje zdrowie.


2

Użyj shell_plus z konfiguracją ipython. Umożliwi to autoreloadzanim shell_plus automatycznie zaimportuje cokolwiek.

pip install django-extensions
pip install ipython
ipython profile create

Edytuj swój profil ipython ( ~/.ipython/profile_default/ipython_config.py):

c.InteractiveShellApp.exec_lines = ['%autoreload 2']
c.InteractiveShellApp.extensions = ['autoreload']

Otwórz powłokę - pamiętaj, że nie musisz dołączać --ipython:

python manage.py shell_plus

Teraz wszystko zdefiniowane w SHELL_PLUS_PRE_IMPORTSor SHELL_PLUS_POST_IMPORTS( docs ), zostanie automatycznie załadowane!

Zauważ, że jeśli twoja powłoka jest w debugerze (ex pdb.set_trace()), kiedy zapisujesz plik, może to zakłócić ponowne załadowanie.


1
Dziękuję za Twoją odpowiedź. Możesz jednak zauważyć, że poprosiłem o to w 2010 roku. Cieszę się, że po ośmiu latach auto-przeładowanie w końcu działa w shell_plus :)
Mad Wombat


0

Nie jest to dokładnie to, czego chcesz, ale teraz mam tendencję do tworzenia własnych poleceń zarządzania do testowania i majstrowania przy różnych rzeczach.

W poleceniu możesz ustawić grupę lokalnych tak, jak chcesz, a następnie wrzucić do interaktywnej powłoki.

import code

class Command(BaseCommand):
  def handle(self, *args, **kwargs):
     foo = 'bar'
     code.interact(local=locals())

Bez przeładowywania, ale łatwy i mniej denerwujący sposób na interaktywne testowanie funkcjonalności django.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.