Reimportar un módulo en python mientras es interactivo

384

Sé que se puede hacer, pero nunca recuerdo cómo.

¿Cómo se puede reimportar un módulo en Python? El escenario es el siguiente: importo un módulo de forma interactiva y retoco con él, pero luego me enfrento a un error. Arreglo el error en el archivo .py y luego quiero volver a importar el módulo fijo sin salir de Python. Cómo puedo hacerlo ?

Stefano Borini
fuente

Respuestas:

370

Esto debería funcionar:

reload(my.module)

De los documentos de Python

Vuelva a cargar un módulo previamente importado. El argumento debe ser un objeto de módulo, por lo que debe haberse importado correctamente antes. Esto es útil si ha editado el archivo fuente del módulo utilizando un editor externo y desea probar la nueva versión sin salir del intérprete de Python.

Si ejecuta Python 3.4 y versiones posteriores, haga import importlib, luego haga importlib.reload(nameOfModule).

No olvide las advertencias de usar este método:

  • Cuando se recarga un módulo, se retiene su diccionario (que contiene las variables globales del módulo). Las redefiniciones de nombres anularán las definiciones antiguas, por lo que esto generalmente no es un problema, pero si la nueva versión de un módulo no define un nombre que fue definido por la versión anterior, la definición anterior no se elimina.

  • Si un módulo importa objetos de otro módulo utilizando from ... import ..., llamar reload()al otro módulo no redefine los objetos importados de él; una forma de evitar esto es volver a ejecutar la frominstrucción, otra es usar importnombres calificados ( module.*name*).

  • Si un módulo crea instancias de instancias de una clase, la recarga del módulo que define la clase no afecta las definiciones de método de las instancias: continúan utilizando la definición de clase anterior. Lo mismo es cierto para las clases derivadas.

Benjamin Wohlwend
fuente
26
si cargo mis módulos usando from filename import *. ¿Cómo recargar?
Peter Zhu
@PeterZhu para el caso "from mod import fcn", el objeto del módulo no se agrega al espacio de nombre. Por lo tanto, debe importar explícitamente el módulo, para que luego pueda volver a cargarlo. import foo; from foo import bar; reload(foo)
Ted
Intenté la recarga, así como la magia de recarga automática, y veo que el cambio de mi código se refleja en la pila del mensaje de error, pero el error en sí parece estar fuera del código obsoleto (por ejemplo, la línea del error está exactamente en el mismo línea como antes, que he cambiado a un comentario, y un comentario claramente no puede estar causando errores). Mi módulo se carga como una extensión de Jupyter, ¿alguien podría saber si esto requiere una solución diferente? ¡Gracias!
yifanwu
1
Si importó su función como "mod de importación como nombre", debe hacer lo siguiente: 'import importlib importlib.reload (name)'
Noe
Este método podría no anular las referencias de otros módulos al módulo recargado. Consulte stackoverflow.com/a/61617169/2642356 para obtener una solución.
EZLearner
288

En python 3, reload ya no es una función integrada.

Si está utilizando python 3.4+, debería utilizarlo reloaddesde la importlibbiblioteca:

import importlib
importlib.reload(some_module)

Si está utilizando Python 3.2 o 3.3, debe:

import imp  
imp.reload(module)  

en lugar. Ver http://docs.python.org/3.0/library/imp.html#imp.reload

Si está usando ipython, definitivamente considere usar la autoreloadextensión:

%load_ext autoreload
%autoreload 2
Andrés
fuente
Aunque gran parte del código de Python está escrito en Python 2, Python 3 se está convirtiendo en una opción más viable todos los días. ¡Gracias por el consejo!
Aaron Johnson
40
imp.reloadestá en desuso desde Python 3.4, use la importlib.reloadfunción en su lugar.
jfs
1
@ Andrew gracias! Utilicé el% autoreload, es maravilloso, mis objetos ya creados obtuvieron automáticamente la implementación corregida de los métodos de clase sin tener que recrearlos
jeanmi
44
Estoy un poco tarde, pero creo que esto no funciona si lo que necesita para recargar es una función o clase desde dentro del módulo: si mi DECLARACIÓN importación era from mymodule import myfunc, entonces importlib.reload(myfunc), importlib.reload(mymodule.myfunc), importlib.reload(mymodule)todos dan un NameError.
Puff
@Puff vea mi respuesta a continuación sobre cómo volver a importar una función
jss367
46

En realidad, en Python 3 el módulo imp está marcado como DEPRECATED. Bueno, al menos eso es cierto para 3.4.

En su lugar , se debe usar la reloadfunción del importlibmódulo:

https://docs.python.org/3/library/importlib.html#importlib.reload

Pero tenga en cuenta que esta biblioteca tuvo algunos cambios de API con las dos últimas versiones menores.

futuro funky
fuente
6

Si desea importar una función o clase específica desde un módulo, puede hacer esto:

import importlib
import sys
importlib.reload(sys.modules['my_module'])
from my_module import my_function
jss367
fuente
0

Aunque las respuestas proporcionadas funcionan para un módulo específico, no volverán a cargar submódulos, como se indica en esta respuesta :

Si un módulo importa objetos de otro módulo usando from ... import ..., llamar reload()al otro módulo no redefine los objetos importados de él; una forma de evitar esto es volver a ejecutar la declaración from, otra es usar importnombres calificados ( module.*name*).

Sin embargo, si usa la __all__variable para definir la API pública, es posible volver a cargar automáticamente todos los módulos disponibles públicamente:

# Python >= 3.5
import importlib
import types


def walk_reload(module: types.ModuleType) -> None:
    if hasattr(module, "__all__"):
        for submodule_name in module.__all__:
            walk_reload(getattr(module, submodule_name))
    importlib.reload(module)


walk_reload(my_module)

Sin embargo, las advertencias señaladas en la respuesta anterior siguen siendo válidas. En particular, la modificación de un submódulo que no es parte de la API pública como se describe en la __all__variable no se verá afectada por una recarga que use esta función. Del mismo modo, la eliminación de un elemento de un submódulo no se reflejará en una recarga.

skasch
fuente