Reimporte um módulo em python enquanto interativo

383

Eu sei que isso pode ser feito, mas nunca me lembro como.

Como você pode reimportar um módulo em python? O cenário é o seguinte: Eu importo um módulo interativamente e mexo nele, mas então enfrento um erro. Corrijo o erro no arquivo .py e quero reimportar o módulo fixo sem sair do python. Como eu posso fazer isso ?

Stefano Borini
fonte
11
Possível duplicata de Como descarregar (recarregar) um módulo Python?
187 Walter Walter

Respostas:

369

Isso deve funcionar:

reload(my.module)

Dos documentos do Python

Recarregue um módulo importado anteriormente. O argumento deve ser um objeto de módulo, portanto, deve ter sido importado com sucesso antes. Isso é útil se você editou o arquivo de origem do módulo usando um editor externo e deseja experimentar a nova versão sem sair do interpretador Python.

Se você estiver executando o Python 3.4 ou superior, import importlibfaça importlib.reload(nameOfModule).

Não se esqueça das advertências de usar este método:

  • Quando um módulo é recarregado, seu dicionário (contendo as variáveis ​​globais do módulo) é mantido. As redefinições de nomes substituirão as definições antigas, portanto isso geralmente não é um problema, mas se a nova versão de um módulo não definir um nome definido pela versão antiga, a definição antiga não será removida.

  • Se um módulo importa objetos de outro módulo usando from ... import ..., chamar reload()o outro módulo não redefine os objetos importados - uma maneira de contornar isso é reexecutar a frominstrução, outra é usar importnomes qualificados ( module.*name*).

  • Se um módulo instancia instâncias de uma classe, recarregar o módulo que define a classe não afeta as definições de método das instâncias - elas continuam usando a definição de classe antiga. O mesmo vale para classes derivadas.

Benjamin Wohlwend
fonte
26
se eu carregar meus módulos usando from filename import *. Como recarregar?
Peter Zhu
@PeterZhu para o caso "from mod import fcn", o objeto do módulo não é adicionado ao espaço de nome. Portanto, você precisa importar explicitamente o módulo para poder recarregá-lo posteriormente. import foo; from foo import bar; reload(foo)
Ted
Tentei recarregar, assim como a mágica de carregamento automático, e vejo minha alteração de código refletida na pilha da mensagem de erro, mas o erro em si ainda parece estar fora do código obsoleto (por exemplo, a linha do erro está exatamente na mesma linha como antes, que mudei para um comentário e um comentário claramente não pode estar causando erros). Meu módulo está carregado como uma extensão Jupyter. Alguém pode saber se isso requer uma solução alternativa diferente? Obrigado!
yifanwu
11
Se você importou sua função da seguinte forma "import mod as name", precisará fazer o seguinte: 'import importlib importlib.reload (name)'
Noe
Este método pode não substituir as referências de outros módulos para o módulo recarregado. Consulte stackoverflow.com/a/61617169/2642356 para obter uma solução para isso.
EZLearner
288

No python 3, reloadnão é mais uma função integrada.

Se você estiver usando o python 3.4+, você deve usar a reloadpartir da importlibbiblioteca:

import importlib
importlib.reload(some_module)

Se você estiver usando python 3.2 ou 3.3, deverá:

import imp  
imp.reload(module)  

em vez de. Consulte http://docs.python.org/3.0/library/imp.html#imp.reload

Se você estiver usando ipython, definitivamente considere usar a autoreloadextensão:

%load_ext autoreload
%autoreload 2
Andrew
fonte
Embora muitos códigos do Python sejam escritos no Python 2, o Python 3 está se tornando uma opção mais viável todos os dias. Obrigado pela dica!
Aaron Johnson
40
imp.reloadé preterido desde Python 3.4, usar importlib.reloadfunção vez.
JFS
11
@Andrew thanks! Eu usei o autoreload%, é maravilhoso, meus objetos já criados ficou automaticamente a implementação corrigido dos métodos de classe sem ter que recriá-los
jeanmi
4
Eu sou um pouco tarde, mas acho que isso não funciona se o que você precisa de recarga é uma função ou classe de dentro do módulo: se meu statment importação foi from mymodule import myfunc, então importlib.reload(myfunc), importlib.reload(mymodule.myfunc), importlib.reload(mymodule)todos dão uma NameError.
Puff
@ Puff, veja minha resposta abaixo para saber como reimportar uma função
jss367 30/03
46

Na verdade, no Python 3, o módulo impestá marcado como DEPRECATED. Bem, pelo menos isso é verdade para o 3.4.

Em vez disso, a reloadfunção do importlibmódulo deve ser usada:

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

Mas esteja ciente de que esta biblioteca teve algumas alterações de API nas duas últimas versões secundárias.

funky-future
fonte
6

Se você deseja importar uma função ou classe específica de um módulo, você pode fazer isso:

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

Embora as respostas fornecidas funcionem para um módulo específico, elas não recarregam os submódulos, conforme observado em Esta resposta :

Se um módulo importa objetos de outro módulo usando from ... import ..., chamar reload()o outro módulo não redefine os objetos importados - uma maneira de contornar isso é reexecutar a instrução from, outra é usar importnomes qualificados ( module.*name*).

No entanto, se estiver usando a __all__variável para definir a API pública, é possível recarregar automaticamente todos os módulos disponíveis ao público:

# 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)

As advertências observadas na resposta anterior ainda são válidas. Notavelmente, a modificação de um submódulo que não faz parte da API pública, conforme descrito pela __all__variável, não será afetada por um recarregamento usando esta função. Da mesma forma, a remoção de um elemento de um submódulo não será refletida por uma recarga.

skasch
fonte