¿Cómo se descarga (recarga) un módulo?
Tengo un servidor Python que funciona desde hace tiempo y me gustaría poder actualizar un servicio sin reiniciar el servidor. ¿Cuál es la mejor manera de hacerlo?
if foo.py has changed:
unimport foo <-- How do I do this?
import foo
myfoo = foo.Foo()
756
3
Puedes recargar un módulo cuando ya ha sido importado utilizando la función incorporada
reload
:En Python 3,
reload
se trasladó al móduloimp
. En 3.4,imp
quedó obsoleto en favor deimportlib
, yreload
se añadió a este último. Al apuntar a la versión 3 o posterior, se debe hacer referencia al módulo apropiado al llamar areload
o importarlo.Creo que esto es lo que quieres. Los servidores web como el servidor de desarrollo de Django utilizan esto para que puedas ver los efectos de tus cambios de código sin reiniciar el proceso del servidor mismo.
Citando los documentos:
Como has señalado en tu pregunta, tendrás que reconstruir los objetos
Foo
si la claseFoo
reside en el módulofoo
.Puede ser especialmente difícil eliminar un módulo si no es Python puro.
Aquí hay algo de información de: ¿Cómo borro realmente un módulo importado?
Reload(module)
, pero sólo si es completamente independiente. Si cualquier otra cosa tiene una referencia al módulo (o a cualquier objeto que pertenezca al módulo), entonces obtendrás sutiles y curiosos errores causados por el código antiguo que permanece más tiempo del que esperabas, y cosas como
isinstance` que no funcionan en diferentes versiones del mismo código.Si tiene dependencias unidireccionales, también debe recargar todos los módulos que dependen del módulo recargado para deshacerse de todas las referencias al código antiguo. Y luego recargar los módulos que dependen de los módulos recargados, recursivamente.
Si tienes dependencias circulares, lo que es muy común por ejemplo cuando se trata de recargar un paquete, debes descargar todos los módulos del grupo de una sola vez. No puede hacer esto con
reload()
porque reimportará cada módulo antes de que sus dependencias hayan sido refrescadas, permitiendo que las viejas referencias se cuelen en los nuevos módulos.La única manera de hacerlo en este caso es hackear
sys.modules
, lo cual no está soportado. Tendrías que ir y borrar cada entrada desys.modules
que quisieras que se recargara en la siguiente importación, y también borrar las entradas cuyos valores sonNone
para lidiar con un problema de implementación que tiene que ver con el almacenamiento en caché de las importaciones relativas fallidas. No es muy agradable, pero mientras tengas un conjunto de dependencias totalmente autocontenido que no deje referencias fuera de su base de código, es factible.Probablemente sea mejor reiniciar el servidor. :-)