Comment décharger (recharger) un module Python?

j'ai un serveur Python qui fonctionne depuis longtemps et je voudrais pouvoir mettre à jour un service sans redémarrer le serveur. Quelle est la meilleure façon de faire cela?

if foo.py has changed:
    unimport foo  <-- How do I do this?
    import foo
    myfoo = foo.Foo()
628
demandé sur Mark Harrison 2009-01-13 03:33:36

19 réponses

vous pouvez recharger un module alors qu'il a déjà été importé en utilisant la fonction reload builtin en Python 2:

import foo

while True:
    # Do some things.
    if is_changed(foo):
        foo = reload(foo)

en Python 3, reload a été déplacé dans le module imp . Au 3.4, imp a été déprécié en faveur de importlib , et reload a été ajouté à ce dernier. Lorsque vous ciblez 3 ou plus, référez - vous au module approprié lorsque vous appelez reload ou importez-le.

je pense que c'est ce que vous voulez. Les serveurs Web comme le serveur de développement de Django utilisent ceci pour que vous puissiez voir les effets de vos modifications de code sans redémarrer le processus de serveur lui-même.

pour citer les docs:

le code des modules Python est recompilé et le code au niveau du module a été réexaminé, définition d'un nouvel ensemble d'objets qui sont liés aux noms dans le module dictionnaire. La fonction init de les modules d'extension ne sont pas appelés deuxième temps. Comme pour tous les autres objets en Python les vieux objets sont seulement récupérées après leur comptage de référence tomber à zéro. Les noms dans le module espace de noms sont mis à jour pour pointer vers n'importe quel objets nouveaux ou modifiés. Autre les références aux anciens objets (tels que les noms externes au module) ne sont pas rebond pour consulter les nouveaux objets et doit être mis à jour chaque espace de noms où ils se produisent, si cela est souhaité.

comme vous l'avez noté dans votre question, vous devrez reconstruire les objets Foo si la classe Foo réside dans le module foo .

572
répondu cdleary 2017-08-25 15:37:25

en Python 3.0-3.3 vous utiliseriez: imp.reload(module)

Le BDFL a répondu à cette question.

cependant, imp a été déprécié en 3.4, en faveur de importlib (merci @Stefan! ).

je penser , par conséquent, vous feriez maintenant utiliser importlib.reload(module) , bien que je ne sois pas sûr.

237
répondu Paul D. Waite 2017-05-23 12:26:30

il peut être particulièrement difficile de supprimer un module s'il n'est pas Python pur.

voici quelques informations de: Comment puis-je vraiment supprimer un module importé?

vous pouvez utiliser sys.getrefcount () pour connaître le nombre réel de référence.

>>> import sys, empty, os
>>> sys.getrefcount(sys)
9
>>> sys.getrefcount(os)
6
>>> sys.getrefcount(empty)
3
Les nombres

supérieurs à 3 indiquent que il sera difficile de se débarrasser de la module. Le homegrown "vide" (ne contenant rien) module devrait être déchets collectés après

>>> del sys.modules["empty"]
>>> del empty

comme la troisième référence est un artefact de la fonction getrefcount ().

75
répondu Gregg Lind 2014-02-13 22:41:43

reload(module) , mais seulement si c'est complètement autonome. Si quelque chose d'autre a une référence au module (ou n'importe quel objet appartenant au module), alors vous obtiendrez des erreurs subtiles et curieuses causées par l'ancien code qui traîne autour plus longtemps que vous prévu, et des choses comme isinstance ne fonctionne pas à travers 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 vous en débarrasser. toutes les références à l'ancien code. Et puis recharger les modules qui dépendent des modules rechargés, de façon récursive.

si vous avez des dépendances circulaires, ce qui est très courant par exemple quand vous avez affaire à recharger un paquet, vous devez décharger tous les modules du groupe en une seule fois. Vous ne pouvez pas faire cela avec reload() parce qu'il va réimporter chaque module avant que ses dépendances aient été rafraîchies, permettant aux anciennes références de se glisser dans de nouveaux modules.

la seule façon de le faire dans ce cas est de hacker sys.modules , qui est en quelque sorte non supporté. Vous devez passer par et supprimer chaque entrée sys.modules que vous voulez recharger sur la prochaine importation, et aussi supprimer les entrées dont les valeurs sont None pour traiter d'un problème de mise en œuvre à faire avec la mise en cache des importations relatives. Ce n'est pas très agréable, mais tant que vous avez un ensemble complet de dépendances qui ne laisse pas de références en dehors de sa base de données, c'est faisable.

Il est probablement préférable de redémarrer le serveur. :- )

59
répondu bobince 2015-07-14 06:15:43
if 'myModule' in sys.modules:  
    del sys.modules["myModule"]
54
répondu Kumaresan 2015-08-04 06:36:45

pour Python 2 utiliser la fonction intégrée recharger () :

reload(module)

pour Python 2 et 3.2–3.3 utiliser recharger à partir du module imp :

import imp
imp.reload(module)

mais imp est déprécié depuis la version 3.4 en faveur de l'importlib , donc utiliser:

import importlib
importlib.reload(module)

ou

from importlib import reload
reload(module)
35
répondu goetzc 2017-10-05 19:42:57

le code suivant vous permet une compatibilité Python 2/3:

try:
    reload
except NameError:
    # Python 3
    from imp import reload

vous pouvez l'utiliser comme reload() dans les deux versions, ce qui rend les choses plus simples.

20
répondu Matt Clarkson 2012-11-20 16:01:08

la réponse acceptée ne gère pas le cas de x import Y. Ce code le gère ainsi que le cas d'importation standard:

def importOrReload(module_name, *names):
    import sys

    if module_name in sys.modules:
        reload(sys.modules[module_name])
    else:
        __import__(module_name, fromlist=names)

    for name in names:
        globals()[name] = getattr(sys.modules[module_name], name)

# use instead of: from dfly_parser import parseMessages
importOrReload("dfly_parser", "parseMessages")

dans le cas du rechargement, nous réattribuons les noms de niveau supérieur aux valeurs stockées dans le module nouvellement rechargé, qui les met à jour.

14
répondu Joseph Garvin 2014-09-28 02:26:31

C'est la façon moderne de recharger un module:

from importlib import reload

tapez juste reload(MODULE_NAME) , en remplaçant MODULE_NAME par le nom du module que vous voulez recharger.

par exemple, reload(math) rechargera la fonction mathématique.

7
répondu Richie Bendall 2018-08-04 04:33:47

pour ceux comme moi qui veulent décharger tous les modules (en tournant dans l'interpréteur Python sous Emacs ):

   for mod in sys.modules.values():
      reload(mod)

plus d'informations dans recharger les modules Python .

6
répondu Arkadiy 2012-07-12 17:51:29

si vous êtes pas dans un serveur, mais en développement et avez besoin de recharger fréquemment un module, voici un bon conseil.

tout d'abord , assurez-vous que vous utilisez l'excellent IPython shell , du projet de carnet Jupyter. Après avoir installé Jupyter, vous pouvez le démarrer avec ipython , ou jupyter console , ou encore mieux, jupyter qtconsole , ce qui vous donnera une belle console colorisée avec le code achèvement dans tous les OS.

maintenant dans votre coquille, tapez:

%load_ext autoreload
%autoreload 2

maintenant, chaque fois que vous exécutez votre script, vos modules seront rechargés.

au-delà du 2 , il y a d'autres options de la magie de chargement automatique :

%autoreload
Reload all modules (except those excluded by %aimport) automatically now.

%autoreload 0
Disable automatic reloading.

%autoreload 1
Reload all modules imported with %aimport every time before executing the Python code typed.

%autoreload 2
Reload all modules (except those excluded by %aimport) every time before
executing the Python code typed.
6
répondu neves 2018-05-08 17:56:46

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. Il ne fonctionne pas la plupart du temps avec les méthodes __very_private__ , et peut étouffer sur l'héritage de classe, mais il me sauve des quantités folles de temps d'avoir à redémarrer l'application hôte lors de L'écriture PyQt guis, ou des choses qui court à l'intérieur de programmes tels que Maya ou Nuke. Ça ne marche peut-être pas 20-30% du temps, mais c'est quand même incroyablement utile.

le paquet de Enthought ne recharge pas les fichiers au moment où ils changent - vous devez l'appeler explicitement - mais cela ne devrait pas être si difficile à implémenter si vous en avez vraiment besoin

5
répondu flipthefrog 2016-01-09 01:06:14

2018-02-01

  1. module foo doit être importé avec succès à l'avance.
  2. from importlib import reload , reload(foo)

31.5. importlib-la mise en œuvre d'import-Python 3.6.4 documentation

2
répondu JawSaw 2018-02-01 03:44:57

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'elle a besoin de temps pour recompiler pyc (jusqu'à 60 secondes).J'écris cet indice juste que vous savez si vous avez expérimenté ce genre de problème.

2
répondu PythonMan 2018-05-17 11:00:43

pour moi, pour le cas d'Abaqus c'est la façon dont il fonctionne. Imaginez que votre dossier est Class_VerticesEdges.py

sys.path.append('D:\...\My Pythons')
if 'Class_VerticesEdges' in sys.modules:  
    del sys.modules['Class_VerticesEdges']
    print 'old module Class_VerticesEdges deleted'
from Class_VerticesEdges import *
reload(sys.modules['Class_VerticesEdges'])
1
répondu Matt S 2016-02-05 14:27:12

autre option. Voyez que la valeur par défaut de Python importlib.reload va réimporter la bibliothèque passée en argument. ne sera pas recharger les bibliothèques que votre lib importation. Si vous avez changé beaucoup de fichiers et que vous avez un paquet assez complexe à importer, vous devez faire un Deep reload .

si vous avez IPython ou Jupyter installé, vous pouvez utiliser une fonction pour recharger tous libs:

from IPython.lib.deepreload import reload as dreload
dreload(foo)

si vous n'avez pas Jupyter, installez-le avec cette commande dans votre coquille:

pip3 install jupyter
1
répondu neves 2018-05-16 13:37:48

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 basé sur le code sublime_plugin.py utilise pour recharger des modules.

ce qui suit vous permet de recharger des 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.

def reload_module(full_module_name):
    """
        Assuming the folder `full_module_name` is a folder inside some
        folder on the python sys.path, for example, sys.path as `C:/`, and
        you are inside the folder `C:/Path With Spaces` on the file 
        `C:/Path With Spaces/main.py` and want to re-import some files on
        the folder `C:/Path With Spaces/tests`

        @param full_module_name   the relative full path to the module file
                                  you want to reload from a folder on the
                                  python `sys.path`
    """
    import imp
    import sys
    import importlib

    if full_module_name in sys.modules:
        module_object = sys.modules[full_module_name]
        module_object = imp.reload( module_object )

    else:
        importlib.import_module( full_module_name )

def run_tests():
    print( "\n\n" )
    reload_module( "Path With Spaces.tests.semantic_linefeed_unit_tests" )
    reload_module( "Path With Spaces.tests.semantic_linefeed_manual_tests" )

    from .tests import semantic_linefeed_unit_tests
    from .tests import semantic_linefeed_manual_tests

    semantic_linefeed_unit_tests.run_unit_tests()
    semantic_linefeed_manual_tests.run_manual_tests()

if __name__ == "__main__":
    run_tests()

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 arrive souvent parce que son interpréteur ne ferme jamais (à moins que vous ne redémarriez Sublime Text, i.e., l'interpréteur Python3.3 ).

0
répondu user 2017-11-10 09:44:04

une Autre façon serait d'importer le module dans une fonction. De cette façon, lorsque la fonction est terminée, le module reçoit les ordures.

-1
répondu hackbot89 2015-02-11 21:13:42

l'opération unload peut être facilement effectuée comme ceci:

import pythonlib
del pythonlib

vous n'aurez plus rien à voir avec cette bibliothèque.

-1
répondu Mincă Daniel Andrei 2018-08-16 13:12:01