Tengo un servidor Python de larga ejecución y me gustaría poder actualizar un servicio sin reiniciar el servidor. ¿Cuál es la mejor manera de hacer esto?
if foo.py has changed:
unimport foo <-- How do I do this?
import foo
myfoo = foo.Foo()
python
module
reload
python-import
Mark Harrison
fuente
fuente
Respuestas:
Puede volver a cargar un módulo cuando ya se ha importado utilizando la
reload
función incorporada (solo Python 3.4+) :En Python 3,
reload
se movió alimp
módulo. En 3.4,imp
quedó en desuso a favor deimportlib
, yreload
se agregó a este último. Cuando apunte a 3 o posterior, haga referencia al módulo apropiado al llamarreload
o impórtelo.Creo que esto es lo que quieres. Los servidores web como el servidor de desarrollo de Django usan esto para que pueda ver los efectos de los cambios en su código sin reiniciar el proceso del servidor.
Para citar de los documentos:
Como señaló en su pregunta, tendrá que reconstruir
Foo
objetos si laFoo
clase reside en elfoo
módulo.fuente
X
no es un módulo, puedeimport sys; reload(sys.modules[X.__module__])
is_changed
función es solo una función arbitraria que tendrías que escribir; No es un incorporado. Por ejemplo, podría abrir el archivo correspondiente al módulo que está importando y diferenciarlo con una versión en caché para ver si ha cambiado.En Python 3.0–3.3 usarías:
imp.reload(module)
El BDFL ha respondido esta pregunta.
Sin embargo,
imp
quedó en desuso en 3.4, a favor deimportlib
(¡gracias @Stefan! ).Yo pienso , por lo tanto, tendría ahora utiliza
importlib.reload(module)
, aunque no estoy seguro.fuente
reload(__builtins__)
es válido en 2.xPuede ser especialmente difícil eliminar un módulo si no es Python puro.
Aquí hay información de: ¿Cómo elimino realmente un módulo importado?
fuente
setattr(package, "empty", None)
reload()
solo vuelve a cargar el módulo superior y todo lo que contenga no se volverá a cargar a menos que primero lo elimine de sys.modules.reload(module)
, pero solo si es completamente independiente. Si algo más tiene una referencia al módulo (o cualquier objeto que pertenezca al módulo), obtendrá errores sutiles y curiosos causados por el código antiguo que duró más de lo esperado, y cosas comoisinstance
no funcionar en diferentes versiones del mismo códigoSi tiene dependencias unidireccionales, también debe volver a cargar todos los módulos que dependen del módulo recargado para deshacerse de todas las referencias al código anterior. Y luego vuelva a cargar los módulos que dependen de los módulos recargados, de forma recursiva.
Si tiene dependencias circulares, lo cual es muy común, por ejemplo, cuando se trata de recargar un paquete, debe descargar todos los módulos del grupo de una vez. No puede hacer esto
reload()
porque reimportará cada módulo antes de que se actualicen sus dependencias, lo que permitirá que las referencias antiguas se introduzcan en módulos nuevos.La única forma de hacerlo en este caso es hackear
sys.modules
, lo que no es compatible. Tendría que revisar y eliminar cadasys.modules
entrada que desea que se vuelva a cargar en la próxima importación, y también eliminar las entradas cuyos valores sonNone
para tratar un problema de implementación relacionado con el almacenamiento en caché de importaciones relativas fallidas. No es terriblemente agradable, pero siempre que tenga un conjunto de dependencias totalmente autónomo que no deje referencias fuera de su base de código, es viable.Probablemente sea mejor reiniciar el servidor. :-)
fuente
None
valores porque me encuentro exactamente con este problema: estoy eliminando elementos desys.modules
y después de volver a importar algunas dependencias importadasNone
?None
entradas lograron regresar a través del mecanismo de importación cuando se eliminaron las entradas 'reales', y parece que no puedo hacer que suceda en 2.7; en el futuro ciertamente ya no es un problema ya que las importaciones relativas implícitas se han ido. Mientras tanto, eliminar todas las entradas conNone
valor parece solucionarlo.reload
función? Está integrado, no tiene que importar ninguna biblioteca.fuente
nose.run()
, incluso despuésreload(my_module)
%run my_module
[del(sys.modules[mod] for mod in sys.modules.keys() if mod.startswith('myModule.')]
.import sys; import json; del sys.modules['json']; print(json.dumps([1]))
y el módulo json todavía funciona, aunque ya no está en sys.modules.Para Python 2, use la función incorporada reload () :
Para Python 2 y 3.2–3.3 use reload from module imp :
Pero
imp
está en desuso desde la versión 3.4 a favor de importlib , así que use:o
fuente
from six import reload_module
(es necesariopip install six
primero, por supuesto)from six.moves import reload_module
( doc )El siguiente código le permite la compatibilidad con Python 2/3:
Puede usarlo como
reload()
en ambas versiones, lo que simplifica las cosas.fuente
La respuesta aceptada no maneja el caso de X import Y. Este código lo maneja y el caso de importación estándar también:
En el caso de recarga, reasignamos los nombres de nivel superior a los valores almacenados en el módulo recién recargado, que los actualiza.
fuente
>>> from X import Y
de recargar do>>> __import__('X', fromlist='Y')
fromlist='*'
?from
en las declaraciones de importación. Simplementeimport <package>
paquete y símbolo explícito en el código. Tenga en cuenta que esto no siempre es posible o deseable. (Aquí hay una excepción: de la futura función print_import.)foo = reload(foo); from foo import *
Esta es la forma moderna de recargar un módulo:
Si desea admitir versiones de Python anteriores a la 3.5, intente esto:
Para usarlo, ejecute
reload(MODULE)
, reemplazandoMODULE
con el módulo que desea volver a cargar.Por ejemplo,
reload(math)
volverá a cargar elmath
módulo.fuente
from importlib import reload
. Entonces puedes hacerreload(MODULE_NAME)
. No hay necesidad de esta función.modulereload(MODULE_NAME)
se explica más que soloreload(MODULE_NAME)
y tiene menos posibilidades de entrar en conflicto con otras funciones.Si usted es no en un servidor, pero el desarrollo y la necesidad de recargar con frecuencia un módulo, he aquí una buena propina.
Primero, asegúrese de estar utilizando el excelente shell de IPython , del proyecto Jupyter Notebook. Después de instalar Jupyter, puede comenzar con
ipython
ojupyter console
, o incluso mejorjupyter qtconsole
, lo que le dará una buena consola coloreada con finalización de código en cualquier sistema operativo.Ahora en su shell, escriba:
Ahora, cada vez que ejecute su script, sus módulos se recargarán.
Más allá del
2
, hay otras opciones de la magia de autocarga :fuente
Para aquellos como yo que desean descargar todos los módulos (cuando se ejecutan en el intérprete de Python en Emacs ):
Más información se encuentra en los módulos de recarga Python .
fuente
sys.modules.values()
es un módulo. Por ejemplo: >>> type (sys.modules.values () [1]) <class 'email.LazyImporter'> Entonces, si trato de ejecutar ese código, se cae (Sé que no es una solución práctica, solo señalando eso).if mod and mod.__name__ != "__main__": imp.reload(mod)
Enthought Traits tiene un módulo que funciona bastante bien para esto. https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html
Recargará cualquier módulo que se haya cambiado y actualizará otros módulos y objetos instanciados que lo estén utilizando. No funciona la mayoría de las veces con
__very_private__
métodos, y puede ahogarse con la herencia de clase, pero me ahorra una gran cantidad de tiempo al tener que reiniciar la aplicación host al escribir guiones PyQt, o cosas que se ejecutan dentro de programas como Maya o Nuke. No funciona tal vez el 20-30% del tiempo, pero sigue siendo increíblemente útil.El paquete de Enthought no recarga los archivos en el momento en que cambian, debe llamarlo explícitamente, pero eso no debería ser tan difícil de implementar si realmente lo necesita
fuente
Aquellos que usan python 3 y recargan desde importlib.
Si tiene problemas, parece que el módulo no se recarga ... Eso se debe a que necesita un poco de tiempo para volver a compilar pyc (hasta 60 segundos) .Escribo esta sugerencia solo para saber si ha experimentado este tipo de problema.
fuente
2018-02-01
foo
debe importarse con éxito por adelantado.from importlib import reload
,reload(foo)
31.5. importlib - La implementación de import - Documentación de Python 3.6.4
fuente
Otra opción. Vea que el valor predeterminado de Python
importlib.reload
solo volverá a importar la biblioteca pasada como argumento. No volverá a cargar las bibliotecas que importa su lib. Si cambió muchos archivos y tiene un paquete algo complejo para importar, debe realizar una recarga profunda .Si tiene instalado IPython o Jupyter , puede usar una función para volver a cargar todas las bibliotecas:
Si no tiene Jupyter, instálelo con este comando en su shell:
fuente
reload() argument must be module
. Estoy usando una importación de función personalizada y parece que no funciona. El uso de módulos integrados funciona. :-( es una pérdida de tiempo volver a cargar iPython por cada pequeño cambio que hice en mi código ...Editar (Respuesta V2)
La solución anterior es buena solo para obtener la información de reinicio, pero no cambiará todas las referencias (más de
reload
pero menos de lo requerido). Para configurar realmente todas las referencias también, tuve que ir al recolector de basura y reescribir las referencias allí. ¡Ahora funciona como un encanto!Tenga en cuenta que esto no funcionará si el GC está apagado, o si vuelve a cargar datos que no son monitoreados por el GC. Si no quiere meterse con el GC, la respuesta original podría ser suficiente para usted.
Nuevo código:
Respuesta original
Como está escrito en la respuesta de @ bobince, si ya hay una referencia a ese módulo en otro módulo (especialmente si se importó con la
as
palabra clave likeimport numpy as np
), esa instancia no se sobrescribirá.Esto resultó bastante problemático para mí al aplicar pruebas que requerían un estado "limpio" de los módulos de configuración, así que escribí una función llamada
reset_module
que usaimportlib
lareload
función y sobrescribe recursivamente todos los atributos del módulo declarado. Ha sido probado con Python versión 3.6.Nota: ¡ Usar con cuidado! El uso de estos en módulos no periféricos (módulos que definen clases usadas externamente, por ejemplo) podría conducir a problemas internos en Python (como problemas de decapado / no decapado).
fuente
para mí para el caso de Abaqus es la forma en que funciona. Imagine que su archivo es Class_VerticesEdges.py
fuente
Tuve muchos problemas para intentar volver a cargar algo dentro de Sublime Text, pero finalmente pude escribir esta utilidad para recargar módulos en Sublime Text en función del código
sublime_plugin.py
utilizado para recargar módulos.Lo siguiente acepta que recargue módulos desde rutas con espacios en sus nombres, luego, después de volver a cargar, puede importar como lo hace normalmente.
Si ejecuta por primera vez, esto debería cargar el módulo, pero si luego puede volver a utilizar el método / función
run_tests()
, volverá a cargar los archivos de prueba. Con Sublime Text (Python 3.3.6
) esto sucede mucho porque su intérprete nunca se cierra (a menos que reinicie Sublime Text, es decir, elPython3.3
intérprete).fuente
Otra forma podría ser importar el módulo en una función. De esta manera, cuando la función se completa, el módulo obtiene basura recolectada.
fuente
sys.modules
.