2010-03-28 17 views
21

Estoy depurando desde la consola de python y me gustaría volver a cargar un módulo cada vez que hago un cambio para no tener que salir de la consola y volver a ingresarlo. Que estoy haciendo:Forma correcta de volver a cargar un módulo python desde la consola

>>> from project.model.user import * 
>>> reload(user) 

pero recibo:

>>>NameError: name 'user' is not defined 

¿Cuál es la forma correcta para recargar toda la clase de usuario? ¿Hay una mejor manera de hacerlo, tal vez la actualización automática durante la depuración?

Gracias.

Respuesta

29

Como pidió, lo mejor que puede hacer es

>>> from project.models.user import * 
>>> import project # get module reference for reload 
>>> reload(project.models.user) # reload step 1 
>>> from project.models.user import * # reload step 2 

sería mejor y más limpia si se ha utilizado el módulo de usuario directamente, en lugar de hacer import * (que casi nunca es la forma correcta de hacerlo) . Entonces solo sería

>>> from project.models import user 
>>> reload(user) 

Esto haría lo que usted quisiera. Pero, no es muy agradable. Si realmente necesita volver a cargar los módulos con tanta frecuencia, tengo que preguntar: ¿por qué?

Mi sospecha (respaldada por la experiencia previa con personas que hacen preguntas similares) es que está probando su módulo. Hay muchas maneras de probar un módulo, y hacerlo a mano en el intérprete interactivo es una de las peores maneras. Guarde una de sus sesiones en un archivo y use doctest, para una solución rápida. Alternativamente, escríbalo como un programa y usa python -i. La única gran solución, sin embargo, es usar el módulo unittest.

Si eso no es, con suerte es algo mejor, no peor. Realmente no hay un buen uso de reload (de hecho, se elimina en 3.x). No funciona de manera efectiva. Puede volver a cargar un módulo pero dejar restos de versiones anteriores. Ni siquiera funciona en todo tipo de módulos: los módulos de extensión no se vuelven a cargar correctamente o, a veces, incluso se rompen de forma horrible cuando se vuelven a cargar.

El contexto de uso en el intérprete interactivo no deja muchas opciones en cuanto a lo que está haciendo, y cuál sería la mejor solución real.Fuera de él, a veces las personas usaban reload() para implementar complementos, etc. Esto es peligroso en el mejor de los casos, y con frecuencia se puede hacer de manera diferente usando exec (ah, el territorio malvado en el que nos encontramos), o un proceso segregado.

+0

+1: Realmente no hay un buen uso de la recarga. –

+0

Lo que estoy haciendo para encontrar esta pregunta, es que estoy usando la consola para explorar una estructura de datos importada de JSON. Quiero utilizar "recargar" para mantener algunas funciones en mi editor de texto que atraviesan la estructura de diferentes maneras, edítelas y vuelva a ejecutarlas, sin tener que salir de la consola. Aún así, si Python no puede soportar eso limpiamente, por razones de implementación como esta incapacidad para eliminar "sobras", creo que debo estar equivocado al querer hacerlo ;-p +1 por la respuesta que me permite hacerlo de todos modos, aunque. –

+0

+1 por mostrarme que realmente debería escribir pruebas en lugar de hacer cosas en el intérprete a mano, incluso para afinar. Esto también sería útil para futuras pruebas de no regresión. –

4

Por desgracia tienes que utilizar:

>>> from project.model import user 
>>> reload(user) 

No sé la parte superior de la cabeza de algo que volverá a cargar automáticamente los módulos en el modo interactivo ... Pero no veo ninguna razón uno no debería existir (de hecho, no sería demasiado difícil de aplicar, ya sea ...)

Ahora, usted podría hacer algo como esto:

from types import ModuleType 
import sys 
_reload_builtin = reload 
def reload(thing): 
    if isinstance(thing, ModuleType): 
     _reload_builtin(thing) 
    elif hasattr(thing, '__module__') and thing.__module__: 
     module = sys.modules[thing.__module__] 
     _reload_builtin(module) 
    else: 
     raise TypeError, "reload() argument must be a module or have an __module__" 
4

No puede usar reload() de manera efectiva.

Python no proporciona un soporte efectivo para la recarga o descarga de módulos previamente importados; las referencias de módulos hacen que no sea práctico volver a cargar un módulo porque podrían existir referencias en muchos lugares de su programa.

Python 3 ha eliminado por completo la función de recarga().

+1

No son referencias de módulos que lo hacen: reload() realmente muta el objeto del módulo. Son las referencias a funciones y clases dentro del módulo las que rompen cosas (en particular, las referencias generadas por from foo import *). –

+0

Sí, estoy de acuerdo, y podría tener otros módulos de programa que hayan importado el módulo que desea descargar(). – systempuntoout

1

IPython puede volver a cargar los módulos antes de ejecutar cada nueva línea:

%load_ext autoreload 
%autoreload 2 

Dónde %autoreload 2 recargas "todos los módulos (excepto los excluidos por aimport%) cada vez antes de ejecutar el código Python escrito"

Consulte los documentos:

1

Para python3, la recarga se ha trasladado al módulo de imp. puede usar imp.reload(). Puede consultar this post.

>>> import imp 
>>> import project # get module reference for reload 
>>> imp.reload(project.models.user) # reload step 1 
>>> from project.models.user import * # reload step 2 
Cuestiones relacionadas