Come ricaricare i moduli nella shell di django?


90

Sto lavorando con Django e uso sempre la shell Django. La parte fastidiosa è che mentre il server Django si ricarica alle modifiche al codice, la shell no, quindi ogni volta che apporto una modifica a un metodo che sto testando, devo uscire dalla shell e riavviarla, reimportare tutti i moduli che ho bisogno, reinizializza tutte le variabili di cui ho bisogno, ecc. Anche se la cronologia di iPython consente di risparmiare molto sulla digitazione, questo è ancora un problema. C'è un modo per ricaricare automaticamente la shell di django, allo stesso modo del server di sviluppo di django?

Conosco reload (), ma importa molti modelli e generalmente uso la from app.models import *sintassi, quindi reload () non è di grande aiuto.


2
È necessario aggiornare questa domanda per contrassegnare la risposta "django-extensions" corretta.
woodardj

1
Non finché non funziona davvero per me. Ho le estensioni installate e nessuno dei miei codici si ricarica automaticamente e non vedo alcuna menzione del ricaricamento automatico nella documentazione di shell_plus. Sembra che ci sia un reloader nel comando runserver_plus, ma non è quello che sto cercando.
Mad Wombat

Risposte:


37

Consiglio di utilizzare il progetto django-extensions come indicato sopra da dongweiming. Ma invece del solo comando di gestione 'shell_plus', usa:

manage.py shell_plus --notebook

Questo aprirà un notebook IPython sul tuo browser web. Scrivi il tuo codice lì in una cella, le tue importazioni ecc. Ed eseguilo.

Quando modifichi i moduli, fai clic sulla voce di menu del notebook "Kernel-> Restart"

Ecco fatto, il tuo codice ora utilizza i tuoi moduli modificati.


30
"Usa solo un taccuino Python" non è una risposta alla domanda dell'OP.
J__

Questo metodo, sebbene non automatico come% autoreload, funziona in modo più affidabile rispetto al caricamento automatico. Il riavvio del kernel garantisce che tutte le celle del notebook vengano ricaricate completamente. Inoltre puoi riavviare ed eseguire tutte le celle se lo desideri.
Anton I. Sipos

72

Suggerirei di utilizzare l' estensione di caricamento automatico IPython .

./manage.py shell

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

E da ora tutti i moduli importati verranno aggiornati prima di valutare.

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'

Funziona anche se qualcosa è stato importato prima del %load_ext autoreloadcomando.

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

È anche possibile impedire l'aggiornamento di alcune importazioni con il %aimportcomando e 3 strategie di caricamento automatico:

% autoreload

  • Ricarica automaticamente tutti i moduli (eccetto quelli esclusi da% aimport) ora.

% autoreload 0

  • Disabilita il ricaricamento automatico.

% autoreload 1

  • Ricarica tutti i moduli importati con% aimport ogni volta prima di eseguire il codice Python digitato.

% autoreload 2

  • Ricarica tutti i moduli (eccetto quelli esclusi da% aimport) ogni volta prima di eseguire il codice Python digitato.

% aimport

  • Elenca i moduli che devono essere importati automaticamente o che non devono essere importati.

% aimport foo

  • Importa il modulo 'pippo' e contrassegnalo per essere caricato automaticamente per% autoreload 1

% aimport -foo

  • Contrassegna il modulo 'pippo' per non essere caricato automaticamente.

Questo generalmente funziona bene per il mio uso, ma ci sono alcuni cavetas:

  • La sostituzione degli oggetti di codice non sempre riesce: cambiare una proprietà @ in una classe in un metodo ordinario o un metodo in una variabile membro può causare problemi (ma solo nei vecchi oggetti).
  • Le funzioni che vengono rimosse (ad es. Tramite monkey-patch) da un modulo prima che venga ricaricato non vengono aggiornate.
  • I moduli di estensione C non possono essere ricaricati e quindi non possono essere caricati automaticamente.

3
Nel caso tu stia usando django's /manage.py shell_plus... se digiti %load_ext autoreloade poi %autoreload 2, i modelli verranno automaticamente ricaricati.
Fusion

Incredibile, hai reso la mia giornata
Shamsul Arefin Sajib

Nota che hai bisogno di ipython per essere installato per questo, ovviamente. Vedi ad esempio stackoverflow.com/a/47170195/50899
Rabarberski

38

guarda il comando manage.py shell_plus fornito dal progetto django-extensions . Caricherà tutti i file del modello all'avvio della shell. e carica automaticamente qualsiasi modifica ma non è necessario uscire, puoi chiamare direttamente lì


40
Uso shell_plus ei miei modelli non si ricaricano automaticamente, mi manca qualcosa?
Diego Ponciano

30
shell_plus non ricarica i modelli, quindi questo non risponde alla domanda.
aljabear

5
come detto, shell_plus non ricarica i modelli.
zenperttu

2
Forse mi manca qualcosa, ma shell_plus non ricarica nulla per me. Carica tutti i modelli all'avvio, il che è conveniente, ma è così.
Mad Wombat

14
shell_plus PU ricaricare i moduli utilizzando il modulo autoreload. Digita '% load_ext autoreload' e poi '% autoreload 2' - vedi ipython.org/ipython-doc/3/config/extensions/autoreload.html
bbrame

37

La mia soluzione è che scrivo il codice e lo salvo in un file, quindi utilizzo:

python manage.py shell <test.py

Quindi posso apportare la modifica, salvare ed eseguire di nuovo quel comando finché non aggiusto tutto ciò che sto cercando di riparare.


2
Bello e semplice. Una nota, aggiungi exit()in fondo al file py per uscire dalla shell Django in modo più pulito. Grazie.
Marc

Soluzione semplice ed elegante. Buon lavoro.
nikoskip

25

Sembra che il consenso generale su questo argomento sia che python reload () fa schifo e non c'è un buon modo per farlo.


Sbagliato. La risposta di @ dongweiming sopra è la soluzione e dovrebbe essere accettata come la migliore risposta.
Joseph Sheedy

3
Molteplici commenti sulla sua risposta dicono che shell_plus non ricarica i modelli
Mad Wombat

1
L'ho appena testato da solo e non si ricarica. Inoltre, che dire del codice non modello importato a mano?
Mad Wombat

Le classi in un'app che sto usando ora si ricaricano alla grande (Python 3.4.3, Django 1.9b1, django-extensions 1.5.9), incluso un semplice modulo non django e la classe al suo interno. Sono passati 5 anni da questa risposta e sono stati fatti molti sviluppi.
Joseph Sheedy

1
L'ho provato sul mio setup 40 minuti fa e shell_plus non ricarica nulla per me. Django 1.7.10, python 3.4.3, django-extensions 1.5.9.
Mad Wombat


5

Segue la mia soluzione per questo inconveniente. Sto usando 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)

Per Python 3.x , 'reload' deve essere importato utilizzando:

from importlib import reload

Spero che sia d'aiuto. Ovviamente è a scopo di debug.

Saluti.


2

Usa shell_plus con una configurazione ipython. Questo si abiliterà autoreloadprima che shell_plus importi automaticamente qualcosa.

pip install django-extensions
pip install ipython
ipython profile create

Modifica il tuo profilo ipython ( ~/.ipython/profile_default/ipython_config.py):

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

Apri una shell: tieni presente che non è necessario includere --ipython:

python manage.py shell_plus

Ora qualsiasi cosa definita in SHELL_PLUS_PRE_IMPORTSo SHELL_PLUS_POST_IMPORTS( docs ) verrà caricata automaticamente!

Nota che se la tua shell è in un debugger (ex pdb.set_trace()) quando salvi un file, può interferire con il ricaricamento.


1
Grazie per la risposta. Potresti notare però che l'ho chiesto nel 2010. Sono felice di sapere che dopo otto anni l'auto-ricarica funziona finalmente in shell_plus :)
Mad Wombat

1

Invece di eseguire comandi dalla shell Django, puoi impostare un comando di gestione in questo modo e rieseguirlo ogni volta.


0

Non esattamente quello che vuoi, ma ora tendo a costruirmi comandi di gestione per testare e giocherellare con le cose.

Nel comando puoi impostare un gruppo di locali nel modo che preferisci e poi cadere in una shell interattiva.

import code

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

Nessuna ricarica, ma un modo semplice e meno fastidioso per testare interattivamente le funzionalità di django.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.