Eu tenho um servidor Python de execução demorada e gostaria de poder atualizar um serviço sem reiniciar o servidor. Qual é a melhor maneira de fazer isso?
if foo.py has changed:
unimport foo <-- How do I do this?
import foo
myfoo = foo.Foo()
python
module
reload
python-import
Mark Harrison
fonte
fonte
Respostas:
Você pode recarregar um módulo quando ele já tiver sido importado usando a
reload
função incorporada (somente Python 3.4+) :No Python 3,
reload
foi movido para oimp
módulo. Em 3.4,imp
foi preterido em favor deimportlib
ereload
foi adicionado a este último. Ao direcionar 3 ou mais recente, faça referência ao módulo apropriado ao chamáreload
-lo ou importá-lo.Eu acho que é isso que você quer. Servidores da Web como o servidor de desenvolvimento do Django usam isso para que você possa ver os efeitos das alterações no seu código sem reiniciar o processo do servidor.
Para citar os documentos:
Como você observou na sua pergunta, você precisará reconstruir
Foo
objetos se aFoo
classe residir nofoo
módulo.fonte
X
não for um módulo, você podeimport sys; reload(sys.modules[X.__module__])
is_changed
função é apenas uma função arbitrária que você precisaria escrever; não é um built-in. Por exemplo, ele poderia abrir o arquivo correspondente ao módulo que você está importando e diferenciá-lo com uma versão em cache para verificar se ele foi alterado.No Python 3.0-3.3, você usaria:
imp.reload(module)
O BDFL tem respondido a esta pergunta.
No entanto,
imp
foi preterido no 3.4, a favor deimportlib
(obrigado @Stefan! ).Eu acho que , portanto, você usaria agora
importlib.reload(module)
, embora não tenha certeza.fonte
reload(__builtins__)
é válida em 2.xPode ser especialmente difícil excluir um módulo se não for um Python puro.
Aqui estão algumas informações de: Como eu realmente excluo um módulo importado?
fonte
setattr(package, "empty", None)
reload()
apenas recarrega o módulo superior, e qualquer coisa dentro dele não será recarregada, a menos que você o exclua primeiro do sys.modules.reload(module)
, mas somente se for completamente independente. Se qualquer outra coisa tiver uma referência ao módulo (ou qualquer objeto pertencente ao módulo), você receberá erros sutis e curiosos causados pelo código antigo por mais tempo do que o esperado e coisas comoisinstance
não funcionar em versões diferentes do mesmo código.Se você tiver dependências unidirecionais, também deverá recarregar todos os módulos que dependem do módulo recarregado para se livrar de todas as referências ao código antigo. E, em seguida, recarregue os módulos que dependem dos módulos recarregados, recursivamente.
Se você tiver dependências circulares, o que é muito comum, por exemplo, ao lidar com o recarregamento de um pacote, você deve descarregar todos os módulos do grupo de uma só vez. Não é possível fazer isso
reload()
porque ele reimporta cada módulo antes que suas dependências sejam atualizadas, permitindo que referências antigas entrem em novos módulos.A única maneira de fazer isso nesse caso é hackear
sys.modules
, o que é meio que sem suporte. Você precisaria passar e excluir cadasys.modules
entrada que desejava recarregar na próxima importação e também excluir entradas cujos valores devemNone
lidar com um problema de implementação relacionado ao armazenamento em cache de importações relativas com falha. Não é muito agradável, mas contanto que você tenha um conjunto totalmente independente de dependências que não deixa referências fora de sua base de código, é viável.Provavelmente é melhor reiniciar o servidor. :-)
fonte
None
valores porque estou enfrentando exatamente esse problema: estou excluindo itens desys.modules
e depois da reimportação de algumas dependências importadasNone
.None
entradas conseguiram retornar ao mecanismo de importação quando as entradas 'reais' foram excluídas, e não consigo fazer isso acontecer no 2.7; no futuro, certamente não será mais um problema, pois as importações relativas implícitas desapareceram. Enquanto isso, excluir todas as entradas comNone
valor parece corrigi-lo.reload
função? Está embutido, você não precisa importar nenhuma biblioteca.fonte
nose.run()
, mesmo depoisreload(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]))
e o módulo json ainda está funcionando, embora não esteja mais no sys.modules.Para Python 2, use a função interna reload () :
Para Python 2 e 3.2–3.3, use reload from module imp :
Mas
imp
está obsoleto desde a versão 3.4 em favor do importlib , então use:ou
fonte
from six import reload_module
(necessidade depip install six
primeira, claro)from six.moves import reload_module
( doc )O código a seguir permite compatibilidade com Python 2/3:
Você pode usá-lo como
reload()
nas duas versões, o que simplifica as coisas.fonte
A resposta aceita não trata do caso Y de importação de X. Este código lida com ele e também com o caso de importação padrão:
No caso de recarregamento, reatribuímos os nomes de nível superior aos valores armazenados no módulo recém-recarregado, que os atualiza.
fonte
>>> from X import Y
a recarga fazer>>> __import__('X', fromlist='Y')
fromlist='*'
?from
nas declarações de importação. Apenasimport <package>
package.symbol explícito e explícito no código. Perceba que isso nem sempre é possível ou desejável. (Aqui está uma exceção: a partir print_function futura importação.)foo = reload(foo); from foo import *
Esta é a maneira moderna de recarregar um módulo:
Se você deseja oferecer suporte a versões do Python anteriores à 3.5, tente o seguinte:
Para usá-lo, execute
reload(MODULE)
, substituindoMODULE
pelo módulo que você deseja recarregar.Por exemplo,
reload(math)
recarregará omath
módulo.fonte
from importlib import reload
. Então você pode fazerreload(MODULE_NAME)
. Não há necessidade dessa função.modulereload(MODULE_NAME)
é mais auto-explicativo do que justoreload(MODULE_NAME)
e tem uma chance menor de entrar em conflito com outras funções.Se você não está em um servidor, mas está desenvolvendo e precisa recarregar frequentemente um módulo, aqui está uma boa dica.
Primeiro, verifique se você está usando o excelente shell IPython , do projeto Jupyter Notebook. Depois de instalar o Jupyter, você pode iniciá-lo com
ipython
, oujupyter console
, melhor ainda, comjupyter qtconsole
um bom console colorido com conclusão de código em qualquer sistema operacional.Agora no seu shell, digite:
Agora, toda vez que você executar seu script, seus módulos serão recarregados.
Além do
2
, existem outras opções da magia de carregamento automático :fonte
Para aqueles como eu que querem descarregar todos os módulos (quando executados no interpretador Python no Emacs ):
Mais informações estão em Recarregando módulos Python .
fonte
sys.modules.values()
é um módulo. Por exemplo: >>> type (sys.modules.values () [1]) <class 'email.LazyImporter'> Então, se eu tentar executar esse código, ele cai (Eu sei que não é uma solução prática, apenas apontando isso).if mod and mod.__name__ != "__main__": imp.reload(mod)
O Enthought Traits possui um módulo que funciona razoavelmente bem para isso. https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html
Ele recarregará qualquer módulo que foi alterado e atualizará outros módulos e objetos instanciados que o estão usando. Ele não funciona na maioria das vezes com
__very_private__
métodos e pode engasgar com a herança de classe, mas poupa muito tempo de reiniciar o aplicativo host ao escrever guis do PyQt, ou coisas que são executadas em programas como o Maya ou o Nuke. Talvez não funcione entre 20 e 30% do tempo, mas ainda é incrivelmente útil.O pacote da Enthought não recarrega os arquivos no momento em que eles mudam - você precisa chamá-lo explicitamente - mas isso não deve ser tão difícil de implementar se você realmente precisar
fonte
Aqueles que estão usando o python 3 e recarregam a partir do importlib.
Se você tiver problemas como parece que o módulo não é recarregado ... Isso ocorre porque ele precisa de algum tempo para recompilar o pyc (até 60 segundos).
fonte
01/02/2018
foo
deve ser importado com sucesso com antecedência.from importlib import reload
,reload(foo)
31,5 importlib - A implementação de import - documentação do Python 3.6.4
fonte
Outra opção. Veja que o padrão do Python
importlib.reload
apenas reimporta a biblioteca passada como argumento. Ele não recarregará as bibliotecas importadas pela sua lib. Se você alterou muitos arquivos e possui um pacote um pouco complexo para importar, é necessário fazer uma atualização profunda .Se você possui o IPython ou o Jupyter instalado, pode usar uma função para recarregar profundamente todas as bibliotecas:
Se você não possui o Jupyter, instale-o com este comando no seu shell:
fonte
reload() argument must be module
. Estou usando uma importação de função personalizada e parece não funcionar. O uso de módulos internos funciona. :-( que é um desperdício de tempo sendo recarregar ipython para cada pequena mudança que eu fiz para o meu código ...Editar (Resposta V2)
A solução anterior é boa apenas para obter as informações de redefinição, mas não altera todas as referências (mais do que
reload
mas menos que o necessário). Para definir todas as referências também, tive que entrar no coletor de lixo e reescrever as referências lá. Agora isso trabalha como charme!Observe que isso não funcionará se o GC estiver desligado ou se estiver recarregando dados que não são monitorados pelo GC. Se você não quiser mexer com o GC, a resposta original pode ser suficiente para você.
Novo Código:
Resposta original
Conforme escrito na resposta de @ bobince, se já houver uma referência a esse módulo em outro módulo (especialmente se ele foi importado com a
as
palavra - chave likeimport numpy as np
), essa instância não será substituída.Isso me mostrou bastante problemático ao aplicar testes que exigiam um estado "clean-slate" dos módulos de configuração, por isso escrevi uma função denominada
reset_module
que usaimportlib
areload
função de e substitui recursivamente todos os atributos do módulo declarado. Foi testado com o Python versão 3.6.Nota: Use com cuidado! O uso desses módulos em módulos não periféricos (módulos que definem classes usadas externamente, por exemplo) pode levar a problemas internos no Python (como problemas de decapagem / não decapagem).
fonte
para mim, no caso de Abaqus, é assim que funciona. Imagine que seu arquivo é Class_VerticesEdges.py
fonte
Eu tive muitos problemas ao tentar recarregar algo dentro do Sublime Text, mas finalmente pude escrever esse utilitário para recarregar os módulos no Sublime Text com base no código
sublime_plugin.py
usado para recarregar os módulos.Isso abaixo permite que você recarregue módulos de caminhos com espaços em seus nomes; depois, depois de recarregar, você pode apenas importar como costuma fazer.
Se você executar pela primeira vez, isso deverá carregar o módulo, mas se mais tarde você puder novamente o método / função,
run_tests()
ele recarregará os arquivos de teste. Com o Sublime Text (Python 3.3.6
), isso acontece muito porque o intérprete nunca fecha (a menos que você reinicie o Sublime Text, ou seja, oPython3.3
intérprete).fonte
Outra maneira poderia ser importar o módulo em uma função. Dessa forma, quando a função é concluída, o módulo recebe o lixo coletado.
fonte
sys.modules
.