J'ai un serveur Python de longue date et je voudrais pouvoir mettre à niveau un service sans redémarrer le serveur. Quelle est la meilleure façon de procéder?
if foo.py has changed:
unimport foo <-- How do I do this?
import foo
myfoo = foo.Foo()
python
module
reload
python-import
Mark Harrison
la source
la source
Réponses:
Vous pouvez recharger un module lorsqu'il a déjà été importé à l'aide de la
reload
fonction intégrée (Python 3.4+ uniquement) :En Python 3, a
reload
été déplacé vers leimp
module. En 3.4, aimp
été déprécié en faveur deimportlib
, et areload
été ajouté à ce dernier. Lorsque vous ciblez 3 ou une version ultérieure, faites référence au module approprié lors de l'appelreload
ou importez-le.Je pense que c'est ce que tu veux. Les serveurs Web comme le serveur de développement de Django l'utilisent pour que vous puissiez voir les effets de vos modifications de code sans redémarrer le processus serveur lui-même.
Pour citer des documents:
Comme vous l'avez noté dans votre question, vous devrez reconstruire des
Foo
objets si laFoo
classe réside dans lefoo
module.la source
is_changed
fonction est juste une fonction arbitraire que vous auriez à écrire; ce n'est pas un intégré. Par exemple, il pourrait éventuellement ouvrir le fichier correspondant au module que vous importez et le différencier avec une version mise en cache pour voir s'il a changé.Dans Python 3.0–3.3, vous utiliseriez:
imp.reload(module)
Le BDFL a répondu à cette question.
Cependant, a
imp
été déprécié en 3.4, en faveur deimportlib
(merci @Stefan! ).Je pense donc que vous utiliseriez maintenant
importlib.reload(module)
, bien que je ne sois pas sûr.la source
reload(__builtins__)
est valable en 2.xIl peut être particulièrement difficile de supprimer un module s'il ne s'agit pas de Python pur.
Voici quelques informations de: Comment supprimer vraiment un module importé?
la source
setattr(package, "empty", None)
reload()
recharge uniquement le module le plus haut, et tout ce qu'il contient ne sera pas rechargé à moins que vous ne le supprimiez d'abord de sys.modules.reload(module)
, mais uniquement s'il est complètement autonome. Si quelque chose d'autre a une référence au module (ou à tout objet appartenant au module), vous obtiendrez des erreurs subtiles et curieuses causées par l'ancien code qui traîne plus longtemps que prévu, et des choses commeisinstance
ne pas fonctionner sur différentes versions du même code.Si vous avez des dépendances à sens unique, vous devez également recharger tous les modules qui dépendent du module rechargé pour se débarrasser de toutes les références à l'ancien code. Et puis rechargez les modules qui dépendent des modules rechargés, récursivement.
Si vous avez des dépendances circulaires, ce qui est très courant par exemple lorsque vous avez besoin de recharger un package, vous devez décharger tous les modules du groupe en une seule fois. Vous ne pouvez pas faire cela avec
reload()
car il réimportera chaque module avant que ses dépendances aient été actualisées, permettant aux anciennes références de se glisser dans les nouveaux modules.La seule façon de le faire dans ce cas est de pirater
sys.modules
, ce qui n'est pas supporté. Vous devez parcourir et supprimer chaquesys.modules
entrée que vous souhaitez recharger lors de la prochaine importation, et également supprimer les entrées dont les valeursNone
concernent un problème d'implémentation lié à la mise en cache des importations relatives ayant échoué. Ce n'est pas terriblement agréable, mais tant que vous avez un ensemble de dépendances entièrement autonome qui ne laisse pas de références en dehors de sa base de code, c'est réalisable.Il est probablement préférable de redémarrer le serveur. :-)
la source
None
valeurs parce que je rencontre exactement ce problème: je supprime des éléments desys.modules
et après la réimportation de certaines dépendances importéesNone
.None
Je ne sais pas (même en regardant le code import.c) comment les entrées ont réussi à revenir dans le mécanisme d'importation lorsque les «vraies» entrées ont été supprimées, et je n'arrive pas à y arriver sur 2.7; à l'avenir, ce n'est certainement plus un problème car les importations relatives implicites ont disparu. En attendant, la suppression de toutes les entrées avecNone
valeur semble le corriger.reload
fonction? Il est intégré, vous n'avez pas besoin d'importer de bibliothèque.la source
nose.run()
, même aprè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]))
et le module json fonctionne toujours même s'il n'est plus dans les modules sys.modules.Pour Python 2, utilisez la fonction intégrée reload () :
Pour Python 2 et 3.2–3.3, utilisez le rechargement à partir du module imp :
Mais
imp
est déconseillé depuis la version 3.4 en faveur de l'importlib , alors utilisez:ou
la source
from six import reload_module
(besoinpip install six
de bien sûr d'abord)from six.moves import reload_module
( doc )Le code suivant vous permet la compatibilité Python 2/3:
Vous pouvez l'utiliser comme
reload()
dans les deux versions, ce qui simplifie les choses.la source
La réponse acceptée ne gère pas le cas de l'importation X à partir de Y. Ce code le gère ainsi que le cas d'importation standard:
Dans le cas du rechargement, nous réaffectons les noms de niveau supérieur aux valeurs stockées dans le module nouvellement rechargé, qui les met à jour.
la source
>>> from X import Y
pour recharger do>>> __import__('X', fromlist='Y')
fromlist='*'
?from
dans les déclarations d'importation. Package.symbol justeimport <package>
et explicite dans le code. Sachez que cela n'est pas toujours possible ou souhaitable. (Voici une exception: à partir de la future import print_function.)foo = reload(foo); from foo import *
Voici la manière moderne de recharger un module:
Si vous souhaitez prendre en charge les versions de Python antérieures à 3.5, essayez ceci:
Pour l'utiliser, exécutez
reload(MODULE)
en remplaçantMODULE
par le module que vous souhaitez recharger.Par exemple,
reload(math)
rechargera lemath
module.la source
from importlib import reload
. Ensuite, vous pouvez le fairereload(MODULE_NAME)
. Il n'y a pas besoin de cette fonction.modulereload(MODULE_NAME)
c'est plus explicite que justereload(MODULE_NAME)
et a moins de chances d'entrer en conflit avec d'autres fonctions.Si vous n'êtes pas sur un serveur, mais que vous développez et avez besoin de recharger fréquemment un module, voici un bon conseil.
Tout d'abord, assurez-vous d'utiliser l'excellent shell IPython du projet Jupyter Notebook. Après avoir installé Jupyter, vous pouvez le démarrer avec
ipython
, oujupyter console
, ou mieux encorejupyter qtconsole
, qui vous donnera une belle console colorisée avec un code complet dans n'importe quel OS.Maintenant dans votre shell, tapez:
Maintenant, chaque fois que vous exécutez votre script, vos modules seront rechargés.
Au-delà de
2
, il existe d'autres options de la magie de chargement automatique :la source
Pour ceux comme moi qui veulent décharger tous les modules (lors de l'exécution dans l'interpréteur Python sous Emacs ):
Plus d'informations sont dans le rechargement des modules Python .
la source
sys.modules.values()
n'est pas un module. Par exemple: >>> type (sys.modules.values () [1]) <class 'email.LazyImporter'> Donc, si j'essaie d'exécuter ce code, il tombe (je sais que ce n'est pas censé être une solution pratique, juste le soulignant).if mod and mod.__name__ != "__main__": imp.reload(mod)
Enthought Traits a un module qui fonctionne assez bien pour cela. https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html
Il rechargera tout module qui a été modifié et mettra à jour les autres modules et objets instanciés qui l'utilisent. Cela ne fonctionne pas la plupart du temps avec des
__very_private__
méthodes et peut étouffer l'héritage de classe, mais cela me fait gagner beaucoup de temps sans avoir à redémarrer l'application hôte lors de l'écriture de PyQt, ou des choses qui s'exécutent à l'intérieur de programmes tels que Maya ou Nuke. Cela ne fonctionne peut-être pas 20 à 30% du temps, mais c'est toujours incroyablement utile.Le package d'Enthought ne recharge pas les fichiers au moment où ils changent - vous devez l'appeler explicitement - mais cela ne devrait pas être si difficile à mettre en œuvre si vous en avez vraiment besoin
la source
Ceux qui utilisent python 3 et rechargent depuis importlib.
Si vous avez des problèmes comme il semble que le module ne se recharge pas ... C'est parce qu'il faut du temps pour recompiler pyc (jusqu'à 60 sec). J'écris cet indice juste pour savoir si vous avez rencontré ce genre de problème.
la source
2018-02-01
foo
doit être importé avec succès à l'avance.from importlib import reload
,reload(foo)
31.5. importlib - L'implémentation de l'import - Documentation Python 3.6.4
la source
Autre option. Vérifiez que Python par défaut
importlib.reload
ne fera que réimporter la bibliothèque passée en argument. Il ne rechargera pas les bibliothèques que votre bibliothèque importe. Si vous avez modifié beaucoup de fichiers et que vous avez un package quelque peu complexe à importer, vous devez effectuer un rechargement en profondeur .Si vous avez installé IPython ou Jupyter , vous pouvez utiliser une fonction pour recharger en profondeur toutes les bibliothèques:
Si vous n'avez pas Jupyter, installez-le avec cette commande dans votre shell:
la source
reload() argument must be module
. J'utilise une importation de fonction personnalisée et ne semble pas fonctionner. L'utilisation de modules intégrés fonctionne. :-( c'est une perte de temps de recharger iPython pour chaque petite modification que j'ai apportée à mon code ...Modifier (réponse V2)
La solution d'avant est bonne pour obtenir simplement les informations de réinitialisation, mais elle ne changera pas toutes les références (plus que
reload
mais moins que nécessaire). Pour définir également toutes les références, j'ai dû aller dans le garbage collector et y réécrire les références. Maintenant ça marche comme un charme!Notez que cela ne fonctionnera pas si le GC est éteint, ou si le rechargement de données qui n'est pas surveillé par le GC. Si vous ne voulez pas jouer avec le GC, la réponse originale pourrait vous suffire.
Nouveau code:
Réponse originale
Comme écrit dans la réponse de @ bobince, s'il y a déjà une référence à ce module dans un autre module (surtout s'il a été importé avec le
as
mot - clé likeimport numpy as np
), cette instance ne sera pas écrasée.Cela s'est avéré assez problématique pour moi lors de l'application de tests qui nécessitaient un état "net" des modules de configuration, j'ai donc écrit une fonction nommée
reset_module
qui utiliseimportlib
lareload
fonction de et écrase récursivement tous les attributs du module déclaré. Il a été testé avec Python version 3.6.Remarque: à utiliser avec précaution! Leur utilisation sur des modules non périphériques (modules qui définissent des classes utilisées en externe, par exemple) peut entraîner des problèmes internes en Python (tels que des problèmes de pickling / un-pickling).
la source
pour moi pour le cas d'Abaqus c'est la façon dont ça marche. Imaginez que votre fichier est Class_VerticesEdges.py
la source
J'ai eu beaucoup de mal à essayer de recharger quelque chose à l'intérieur de Sublime Text, mais finalement j'ai pu écrire cet utilitaire pour recharger des modules sur Sublime Text en fonction du code
sublime_plugin.py
utilisé pour recharger les modules.Ceci ci-dessous vous permet de recharger les modules à partir de chemins avec des espaces sur leurs noms, puis plus tard après le rechargement, vous pouvez simplement importer comme vous le faites habituellement.
Si vous exécutez pour la première fois, cela devrait charger le module, mais si plus tard vous pouvez à nouveau la méthode / fonction,
run_tests()
il rechargera les fichiers de tests. Avec Sublime Text (Python 3.3.6
), cela se produit souvent car son interprète ne se ferme jamais (sauf si vous redémarrez Sublime Text, c'est-à-dire l'Python3.3
interpréteur).la source
Une autre façon pourrait être d'importer le module dans une fonction. De cette façon, lorsque la fonction se termine, le module récupère les ordures.
la source
sys.modules
.