Wie lade ich Module in der Django-Shell neu?

88

Ich arbeite mit Django und benutze die ganze Zeit die Django-Shell. Der ärgerliche Teil ist, dass der Django-Server bei Codeänderungen zwar neu lädt, die Shell jedoch nicht. Jedes Mal, wenn ich eine zu ändernde Methode ändere, muss ich die Shell beenden und neu starten und alle Module I erneut importieren Ich brauche alle Variablen, die ich brauche, neu zu initialisieren usw. Während der iPython-Verlauf viel Tipparbeit erspart, ist dies immer noch ein Schmerz. Gibt es eine Möglichkeit, das automatische Neuladen der Django-Shell durchzuführen, genauso wie es der Django-Entwicklungsserver tut?

Ich kenne reload (), importiere aber viele Modelle und verwende im Allgemeinen die from app.models import *Syntax. Daher ist reload () keine große Hilfe.

Mad Wombat
quelle
2
Sie sollten diese Frage aktualisieren, um die Antwort "Django-Erweiterungen" als richtig zu markieren.
Woodardj
Erst wenn es bei mir tatsächlich funktioniert. Ich habe die Erweiterungen installiert und keiner meiner Codes wird automatisch neu geladen, und in den shell_plus-Dokumenten wird kein Hinweis auf das automatische Neuladen angezeigt. Es scheint, dass der Befehl runserver_plus einen Reloader enthält, aber das ist nicht das, wonach ich suche.
Mad Wombat

Antworten:

37

Ich empfehle die Verwendung des Django-Extensions-Projekts wie oben angegeben durch Dongweiming. Verwenden Sie jedoch anstelle des Verwaltungsbefehls 'shell_plus' Folgendes:

manage.py shell_plus --notebook

Dadurch wird ein IPython-Notizbuch in Ihrem Webbrowser geöffnet. Schreiben Sie dort Ihren Code in eine Zelle, Ihre Importe usw. und führen Sie ihn aus.

Wenn Sie Ihre Module wechseln, klicken Sie einfach auf den Notebook-Menüpunkt 'Kernel-> Neustart'.

Los geht's, Ihr Code verwendet jetzt Ihre geänderten Module.

mpaf
quelle
27
"Verwenden Sie einfach ein Python-Notizbuch" ist keine Antwort auf die Frage des OP.
J__
Diese Methode ist zwar nicht automatisch wie% autoreload, funktioniert jedoch zuverlässiger als das automatische Laden. Der Kernel-Neustart garantiert, dass alle Zellen im Notebook vollständig neu geladene Module erhalten. Außerdem können Sie alle Zellen neu starten und ausführen, wenn Sie dies wünschen.
Anton I. Sipos
66

Ich würde vorschlagen, die IPython- Autoreload-Erweiterung zu verwenden .

./manage.py shell

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

Ab sofort werden alle importierten Module vor der Auswertung aktualisiert.

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'

Funktioniert auch, wenn vor dem %load_ext autoreloadBefehl etwas importiert wurde .

./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'

Es ist auch möglich zu verhindern, dass einige Importe mit %aimportBefehls- und 3 Autoreload-Strategien aktualisiert werden:

% Autoreload

  • Laden Sie jetzt alle Module (mit Ausnahme der von% aimport ausgeschlossenen) automatisch neu.

% Autoreload 0

  • Deaktivieren Sie das automatische Nachladen.

% Autoreload 1

  • Laden Sie alle mit% aimport importierten Module jedes Mal neu, bevor Sie den eingegebenen Python-Code ausführen.

% Autoreload 2

  • Laden Sie jedes Mal alle Module neu (mit Ausnahme der von% aimport ausgeschlossenen), bevor Sie den eingegebenen Python-Code ausführen.

% Zielport

  • Listen Sie Module auf, die automatisch importiert werden sollen oder nicht.

% aimport foo

  • Importieren Sie das Modul 'foo' und markieren Sie es als autoreloaded für% autoreload 1

% aimport -foo

  • Markieren Sie das Modul 'foo', damit es nicht automatisch geladen wird.

Dies funktioniert im Allgemeinen gut für meinen Gebrauch, aber es gibt einige Cavetas:

  • Das Ersetzen von Codeobjekten ist nicht immer erfolgreich: Das Ändern einer @ -Eigenschaft in einer Klasse in eine normale Methode oder einer Methode in eine Mitgliedsvariable kann Probleme verursachen (jedoch nur in alten Objekten).
  • Funktionen, die vor dem erneuten Laden aus einem Modul entfernt wurden (z. B. durch Affen-Patching), werden nicht aktualisiert.
  • C-Erweiterungsmodule können nicht neu geladen und daher nicht automatisch geladen werden.
Bodolsog
quelle
2
Falls Sie Djangos verwenden /manage.py shell_plus... wenn Sie eingeben %load_ext autoreloadund dann %autoreload 2werden Modelle automatisch neu geladen werden.
Fusion
Erstaunlich, du hast meinen Tag gemacht
Shamsul Arefin Sajib
38

Schauen Sie sich den Befehl manage.py shell_plus an, der vom Projekt django-extensions bereitgestellt wird . Beim Start der Shell werden alle Ihre Modelldateien geladen. Wenn Sie Ihre Änderungen automatisch laden, aber keinen Exit benötigen, können Sie dort direkt anrufen

Dongweiming
quelle
40
Ich benutze shell_plus und meine Modelle werden nicht automatisch neu geladen. Fehlt mir etwas?
Diego Ponciano
30
shell_plus lädt keine Modelle neu, daher beantwortet dies die Frage nicht.
Aljabear
5
Wie gesagt, shell_plus lädt keine Modelle neu.
Zenperttu
2
Vielleicht fehlt mir etwas, aber shell_plus lädt nichts für mich neu. Es lädt alle Modelle beim Start, was praktisch ist, aber das ist es.
Mad Wombat
13
shell_plus KANN Module mithilfe des Autoreload-Moduls neu laden. Geben Sie '% load_ext autoreload' und dann '% autoreload 2' ein - siehe ipython.org/ipython-doc/3/config/extensions/autoreload.html
bbrame
36

Meine Lösung besteht darin, den Code zu schreiben, in einer Datei zu speichern und dann Folgendes zu verwenden:

python manage.py shell <test.py

So kann ich die Änderung vornehmen, diesen Befehl speichern und erneut ausführen, bis ich alles repariere, was ich zu reparieren versuche.

Erik
quelle
2
Schön und einfach. Ein Hinweis: Fügen Sie exit()am Ende der py-Datei hinzu, um die Django-Shell sauberer zu verlassen. Vielen Dank.
Marc
Einfache und elegante Lösung. Gut gemacht.
Nikoskip
25

Es scheint, dass der allgemeine Konsens zu diesem Thema darin besteht, dass Python reload () scheiße ist und es keinen guten Weg gibt, dies zu tun.

Mad Wombat
quelle
Falsch. Die Antwort von @ dongweiming oben ist die Lösung und sollte als beste Antwort akzeptiert werden.
Joseph Sheedy
3
Mehrere Kommentare zu seiner Antwort besagen, dass shell_plus keine Modelle neu lädt
Mad Wombat
1
Ich habe es gerade selbst getestet und es wird nicht neu geladen. Und was ist mit Nicht-Modell-Code, den ich von Hand importiere?
Mad Wombat
Klassen in einer App, die ich jetzt verwende, werden großartig neu geladen (Python 3.4.3, Django 1.9b1, Django-Erweiterungen 1.5.9), einschließlich eines einfachen Nicht-Django-Modellmoduls und der darin enthaltenen Klasse. Seit dieser Antwort sind 5 Jahre vergangen, und es hat sich viel entwickelt.
Joseph Sheedy
1
Ich habe es vor 40 Minuten in meinem Setup versucht und shell_plus lädt nichts für mich neu. Django 1.7.10, Python 3.4.3, Django-Erweiterungen 1.5.9.
Mad Wombat
5

Meine Lösung für diese Unannehmlichkeit folgt. Ich benutze 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)

Für Python 3.x muss 'reload' importiert werden mit:

from importlib import reload

Ich hoffe es hilft. Natürlich ist es für Debug-Zwecke.

Prost.

Roque
quelle
2

Verwenden Sie shell_plus mit einer ipython-Konfiguration. Dies wird aktiviert, autoreloadbevor shell_plus automatisch etwas importiert.

pip install django-extensions
pip install ipython
ipython profile create

Bearbeiten Sie Ihr Ipython-Profil ( ~/.ipython/profile_default/ipython_config.py):

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

Öffnen Sie eine Shell - beachten Sie, dass Sie nicht Folgendes einschließen müssen --ipython:

python manage.py shell_plus

Jetzt wird alles, was in SHELL_PLUS_PRE_IMPORTSoder SHELL_PLUS_POST_IMPORTS( docs ) definiert ist, automatisch geladen!

Beachten Sie, dass wenn sich Ihre Shell beim pdb.set_trace()Speichern einer Datei in einem Debugger (z. B.) befindet, dies das Neuladen beeinträchtigen kann.

andorov
quelle
1
Danke für die Antwort. Sie können jedoch feststellen, dass ich es im Jahr 2010 gefragt habe. Ich bin froh zu wissen, dass nach acht Jahren das automatische Neuladen endlich in shell_plus funktioniert :)
Mad Wombat
1

Statt Befehle aus dem Django - Shell ausgeführt wird , können Sie einen Management - Befehl einrichten wie so und erneut ausgeführt , dass jedes Mal.

thomaspaulb
quelle
0

Nicht genau das, was Sie wollen, aber ich neige jetzt dazu, mir Verwaltungsbefehle zum Testen und Herumspielen zu erstellen.

Mit dem Befehl können Sie eine Reihe von Einheimischen nach Ihren Wünschen einrichten und anschließend in eine interaktive Shell einfügen.

import code

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

Kein Nachladen, aber eine einfache und weniger nervige Möglichkeit, die Django-Funktionalität interaktiv zu testen.

toabi
quelle