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.

Mad Wombat
źródło
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.

mpaf
źródło
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ć.
bodolsog
źródło
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ć

dongweiming
źródło
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ć.

Erik
źródło
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.

Mad Wombat
źródło
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.

Roque
źródło
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.

Andorov
źródło
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
1

Zamiast uruchamiać polecenia z Django powłoki, można skonfigurować polecenie zarządzania podobnie jak i powtórka, że za każdym razem.

mało zielony
źródło
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.

toabi
źródło