¿Cómo recargar módulos en django shell?

90

Estoy trabajando con Django y uso el shell de Django todo el tiempo. La parte molesta es que mientras el servidor Django se recarga con los cambios de código, el shell no lo hace, por lo que cada vez que hago un cambio en un método que estoy probando, necesito salir del shell y reiniciarlo, volver a importar todos los módulos que necesito, reinicializar todas las variables que necesito, etc. Si bien el historial de iPython ahorra mucho escribir en esto, esto sigue siendo un problema. ¿Hay alguna manera de hacer que django shell se recargue automáticamente, de la misma manera que lo hace el servidor de desarrollo de django?

Sé sobre reload (), pero importo muchos modelos y generalmente uso from app.models import *sintaxis, por lo que reload () no es de mucha ayuda.

Wombat loco
fuente
2
Debería actualizar esta pregunta para marcar la respuesta de "django-extensions" como correcta.
woodardj
1
No hasta que realmente funcione para mí. Tengo las extensiones instaladas y ninguno de mis códigos se recarga automáticamente y no veo ninguna mención de recarga automática en los documentos de shell_plus. Parece que hay un cargador en el comando runserver_plus, pero eso no es lo que estoy buscando.
Mad Wombat

Respuestas:

37

Recomiendo usar el proyecto django-extensions como se indicó anteriormente por dongweiming. Pero en lugar de solo el comando de administración 'shell_plus', use:

manage.py shell_plus --notebook

Esto abrirá un cuaderno IPython en su navegador web. Escriba su código allí en una celda, sus importaciones, etc. y ejecútelo.

Cuando cambie sus módulos, simplemente haga clic en el elemento del menú del cuaderno 'Kernel-> Reiniciar'

Ahí lo tienes, tu código ahora está usando tus módulos modificados.

mpaf
fuente
30
"Simplemente use un cuaderno de Python" no es una respuesta a la pregunta del OP.
J__
Este método, aunque no es automático como el% de recarga automática, funciona de forma más fiable que la recarga automática. El reinicio del kernel garantiza que todas las celdas del portátil obtengan módulos completamente recargados. Además, puede reiniciar y ejecutar todas las celdas si lo desea.
Anton I. Sipos
72

Sugeriría usar la extensión de recarga automática de IPython .

./manage.py shell

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

Y a partir de ahora, todos los módulos importados se actualizarán antes de evaluar.

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'

También funciona si se importó algo antes 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'

También es posible evitar que algunas importaciones se %aimportactualicen con el comando y 3 estrategias de recarga automática:

% de recarga automática

  • Vuelva a cargar todos los módulos (excepto los excluidos por% aimport) automáticamente ahora.

% de recarga automática 0

  • Desactive la recarga automática.

% autorrecarga 1

  • Vuelva a cargar todos los módulos importados con% aimport cada vez antes de ejecutar el código Python escrito.

% de recarga automática 2

  • Vuelva a cargar todos los módulos (excepto los excluidos por% aimport) cada vez antes de ejecutar el código Python escrito.

% puerto objetivo

  • Enumere los módulos que se van a importar automáticamente o que no se van a importar.

% aimport foo

  • Importe el módulo 'foo' y márquelo para que se recargue automáticamente para% autoreload 1

% aimport -foo

  • Marque el módulo 'foo' para que no se recargue automáticamente.

Esto generalmente funciona bien para mi uso, pero hay algunas advertencias:

  • Reemplazar objetos de código no siempre es exitoso: cambiar una @property en una clase a un método ordinario o un método a una variable miembro puede causar problemas (pero solo en objetos antiguos).
  • Las funciones que se eliminan (por ejemplo, mediante el parche de mono) de un módulo antes de volver a cargarlo no se actualizan.
  • Los módulos de extensión C no se pueden recargar y, por lo tanto, no se pueden recargar automáticamente.
Bodolsog
fuente
3
En caso de que esté usando django's /manage.py shell_plus... si escribe %load_ext autoreloady luego %autoreload 2, los modelos se recargarán automáticamente.
Fusion
Increíble, me
alegraste el
Tenga en cuenta que, obviamente, necesita que ipython esté instalado para esto. Ver, por ejemplo, stackoverflow.com/a/47170195/50899
Rabarberski
38

mire el comando manage.py shell_plus proporcionado por el proyecto django-extensions . Cargará todos los archivos de su modelo al iniciar el shell. y recargue automáticamente cualquier modificación pero no necesita salir, puede llamar directamente allí

dongweiming
fuente
40
Utilizo shell_plus y mis modelos no se recargan automáticamente, ¿me falta algo?
Diego Ponciano
30
shell_plus no recarga los modelos, por lo que esto no responde a la pregunta.
aljabear
5
como se dijo, shell_plus no recarga los modelos.
zenperttu
2
Tal vez me esté perdiendo algo, pero shell_plus no recarga nada por mí. Carga todos los modelos al inicio, lo cual es conveniente, pero eso es todo.
Mad Wombat
14
shell_plus PUEDE recargar módulos usando el módulo de recarga automática. Escriba '% load_ext autoreload' y luego '% autoreload 2'; consulte ipython.org/ipython-doc/3/config/extensions/autoreload.html
bbrame
37

Mi solución es que escribo el código y lo guardo en un archivo y luego uso:

python manage.py shell <test.py

Entonces puedo hacer el cambio, guardar y ejecutar ese comando nuevamente hasta que arregle lo que estoy tratando de arreglar.

Erik
fuente
2
Agradable y sencillo. Una nota, agregue exit()al final del archivo py para salir del shell de Django de una manera más limpia. Gracias.
Marc
Solución simple y elegante. Buen trabajo.
Nikoskip
25

Parece que el consenso general sobre este tema es que python reload () apesta y no hay una buena manera de hacerlo.

Wombat loco
fuente
Incorrecto. La respuesta anterior de @ dongweiming es la solución y debe aceptarse como la mejor respuesta.
Joseph Sheedy
3
Varios comentarios sobre su respuesta dicen que shell_plus no recarga los modelos
Mad Wombat
1
Lo acabo de probar yo mismo y no se recarga. Además, ¿qué pasa con el código que no es modelo que importo a mano?
Mad Wombat
Las clases en una aplicación que estoy usando ahora se recargan genial (Python 3.4.3, Django 1.9b1, django-extensions 1.5.9), incluido un módulo simple sin modelo de django y la clase dentro de él. Han pasado 5 años desde esta respuesta y se ha producido un gran desarrollo.
Joseph Sheedy
1
Lo probé en mi configuración hace 40 minutos y shell_plus no recarga nada por mí. Django 1.7.10, python 3.4.3, django-extensions 1.5.9.
Mad Wombat
5

Mi solución para este inconveniente es la siguiente. Estoy 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)

Para Python 3.x , 'reload' debe importarse usando:

from importlib import reload

Espero eso ayude. Por supuesto, es con fines de depuración.

Salud.

Roque
fuente
2

Utilice shell_plus con una configuración de ipython. Esto se habilitará autoreloadantes de que shell_plus importe automáticamente cualquier cosa.

pip install django-extensions
pip install ipython
ipython profile create

Edite su perfil de ipython ( ~/.ipython/profile_default/ipython_config.py):

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

Abra un caparazón; tenga en cuenta que no es necesario incluir --ipython:

python manage.py shell_plus

¡Ahora cualquier cosa definida en SHELL_PLUS_PRE_IMPORTSo SHELL_PLUS_POST_IMPORTS( docs ) se recargará automáticamente!

Tenga en cuenta que si su shell está en un depurador (ex pdb.set_trace()) cuando guarda un archivo, puede interferir con la recarga.

Andorov
fuente
1
Gracias por la respuesta. Sin embargo, puede notar que lo pregunté en 2010. Me alegra saber que después de ocho años la recarga automática finalmente funciona en shell_plus :)
Mad Wombat
1

En lugar de ejecutar comandos desde el shell de Django, puede configurar un comando de administración como este y volver a ejecutarlo cada vez.

pequeño verde
fuente
0

No es exactamente lo que quieres, pero ahora tiendo a crear comandos de administración para probar y manipular cosas.

En el comando, puede configurar un grupo de locales de la manera que desee y luego colocarlos en un shell interactivo.

import code

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

Sin recarga, pero una forma fácil y menos molesta de probar interactivamente la funcionalidad de django.

toabi
fuente