Réimportez un module en python tout en étant interactif

384

Je sais que cela peut être fait, mais je ne me souviens jamais comment.

Comment réimporter un module en python? Le scénario est le suivant: j'importe un module de manière interactive et je le bricole, mais je fais face à une erreur. Je corrige l'erreur dans le fichier .py puis je souhaite réimporter le module fixe sans quitter python. Comment puis-je le faire ?

Stefano Borini
la source

Réponses:

370

Cela devrait fonctionner:

reload(my.module)

Depuis les documents Python

Rechargez un module précédemment importé. L'argument doit être un objet module, il doit donc avoir été importé avec succès auparavant. Ceci est utile si vous avez édité le fichier source du module à l'aide d'un éditeur externe et que vous souhaitez essayer la nouvelle version sans quitter l'interpréteur Python.

Si vous utilisez Python 3.4 et plus, faites-le import importlib, puis faites-le importlib.reload(nameOfModule).

N'oubliez pas les mises en garde d'utiliser cette méthode:

  • Lorsqu'un module est rechargé, son dictionnaire (contenant les variables globales du module) est conservé. Les redéfinitions de noms remplaceront les anciennes définitions, donc ce n'est généralement pas un problème, mais si la nouvelle version d'un module ne définit pas un nom qui était défini par l'ancienne version, l'ancienne définition n'est pas supprimée.

  • Si un module importe des objets d'un autre module à l'aide from ... import ..., l'appel reload()à l'autre module ne redéfinit pas les objets importés à partir de celui-ci - une façon de contourner cela consiste à réexécuter l' frominstruction, une autre consiste à utiliser importet des noms qualifiés ( module.*name*) à la place.

  • Si un module instancie des instances d'une classe, le rechargement du module qui définit la classe n'affecte pas les définitions de méthode des instances - il continue d'utiliser l'ancienne définition de classe. Il en va de même pour les classes dérivées.

Benjamin Wohlwend
la source
26
si je charge mes modules en utilisant from filename import *. Comment recharger?
Peter Zhu
@PeterZhu pour le cas "from mod import fcn", l'objet module n'est pas ajouté à l'espace de nom. Vous devez donc importer explicitement le module, afin de pouvoir le recharger ultérieurement. import foo; from foo import bar; reload(foo)
Ted
J'ai essayé le rechargement, ainsi que la magie de rechargement automatique, et je vois mon changement de code reflété dans la pile du message d'erreur, mais l'erreur elle-même semble toujours être hors du code périmé (par exemple, la ligne de l'erreur est exactement la même ligne comme précédemment, que j'ai changé en commentaire, et un commentaire ne peut clairement pas être à l'origine d'erreurs). Mon module est chargé en tant qu'extension Jupyter, quelqu'un pourrait-il savoir si cela nécessite un travail différent? Merci!
yifanwu
1
Si vous avez importé votre fonction comme suit "importez le mod en tant que nom", vous devez alors procéder comme suit: 'import importlib importlib.reload (name)'
Noe
Cette méthode peut ne pas remplacer les références des autres modules au module rechargé. Voir stackoverflow.com/a/61617169/2642356 pour une solution à cela.
EZLearner
288

En python 3, reloadn'est plus une fonction intégrée.

Si vous utilisez python 3.4+, vous devez utiliser reloadà la importlibplace à partir de la bibliothèque:

import importlib
importlib.reload(some_module)

Si vous utilisez python 3.2 ou 3.3, vous devez:

import imp  
imp.reload(module)  

au lieu. Voir http://docs.python.org/3.0/library/imp.html#imp.reload

Si vous utilisez ipython, envisagez certainement d'utiliser l' autoreloadextension:

%load_ext autoreload
%autoreload 2
Andrew
la source
Bien qu'une grande partie du code Python soit écrit en Python 2, Python 3 devient chaque jour une option plus viable. Merci pour le conseil!
Aaron Johnson
40
imp.reloadest obsolète depuis Python 3.4, utilisez plutôt la importlib.reloadfonction .
jfs
1
@Andrew merci! J'ai utilisé le% autoreload, c'est merveilleux, mes objets déjà créés ont automatiquement la mise en œuvre corrigée des méthodes de classe sans avoir à les recréer
jeanmi
4
Je suis un peu en retard, mais je pense que cela ne fonctionne pas si ce que vous devez reload est une fonction ou une classe à l' intérieur du module: si mon statment d'importation était from mymodule import myfunc, alors importlib.reload(myfunc), importlib.reload(mymodule.myfunc), importlib.reload(mymodule)tous donnent une NameError.
Puff
@Puff voir ma réponse ci-dessous pour savoir comment réimporter une fonction
jss367
46

En fait, dans Python 3, le module impest marqué comme DÉCONSEILLÉ. Eh bien, au moins, c'est vrai pour la 3.4.

Au lieu de cela, la reloadfonction du importlibmodule doit être utilisée:

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

Mais sachez que cette bibliothèque a subi quelques modifications API avec les deux dernières versions mineures.

funky-future
la source
6

Si vous souhaitez importer une fonction ou une classe spécifique à partir d'un module, vous pouvez le faire:

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

Bien que les réponses fournies fonctionnent pour un module spécifique, elles ne rechargeront pas les sous-modules, comme indiqué dans Cette réponse :

Si un module importe des objets à partir d'un autre module à l'aide from ... import ..., l'appel reload()à l'autre module ne redéfinit pas les objets importés à partir de celui-ci - une façon de contourner cela consiste à réexécuter l'instruction from, une autre consiste à utiliser importet des noms qualifiés ( module.*name*) à la place.

Cependant, si vous utilisez la __all__variable pour définir l'API publique, il est possible de recharger automatiquement tous les modules accessibles au public:

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

Les mises en garde notées dans la réponse précédente sont cependant toujours valables. Notamment, la modification d'un sous-module qui ne fait pas partie de l'API publique comme décrit par la __all__variable ne sera pas affectée par un rechargement à l'aide de cette fonction. De même, la suppression d'un élément d'un sous-module ne sera pas reflétée par un rechargement.

skasch
la source