web-dev-qa-db-fra.com

comment recharger une classe dans un shell python?

Si j'importe un module définissant une classe du même nom appartenant à un package, il est importé en tant que classe et non en tant que module en raison du __init__.py du package parent. Voir différents résultats d'importation dans différents répertoires pour plus de détails. Dans un shell Python ou un shell ipython, si je le fais

from MyPak import MyMod

MyModule est toujours importé en tant que classe et je ne peux donc pas le recharger (reload () ne fonctionne que pour les modules). Courir 

from MyPak import MyMod

encore une fois ne semble pas mettre à jour la définition de classe. Quelqu'un pourrait-il suggérer un moyen de mettre à jour la classe dans un shell python? 

ps. sans redémarrer l'interpréteur python. 

pps. Juste au cas où vous avez le code en main et que vous voulez le tester: je parle en fait de BioPython et je travaille sur Bio.PDB.PDBParser. J'ai un shell ipython (v0.10) et éditer PDBParser.py. Je n'ai aucun moyen de le recharger dans ipython.

alors voici ce que j'ai fait:

# start ipython v0.10
import Bio
from Bio.PDB import PDBParser
p = PDBParser()
s = p.get_structure()
# then I make changes,e.g. simply print some text, in PDBParser.py
del Bio
del PDBParser
del s
import Bio  # or reload(Bio) without deleting all the objects
from Bio.PDB import PDBParser
p = PDBParser()
s = p.get_structure() # expected output after change not seen :(

Je ne pouvais pas voir le texte imprimé. Les modifications n'ont pas été appliquées d'une manière ou d'une autre. 

50
HongboZhu

J'ai finalement trouvé la réponse:

import MyPak
from MyPak import MyMod

après avoir édité le fichier MyPak/MyMod.py, pour recharger la classe MyMod dans le fichier MyMod.py, il faut

import sys
del sys.modules['MyPak.MyMod'] 
reload(MyPak)
from MyPak import MyMod

Mises en garde:

  1. L'exécution de del MyPak ou del MyMod ou del MyPak.MyMod ne résout pas le problème, car elle supprime simplement la liaison de noms. Python ne recherche que sys.modules pour voir si les modules ont déjà été importés. Consultez la discussion dans le post nom du module dans sys.modules and globals () .

  2. Lors du rechargement de MyPak, Python tente d'exécuter la ligne from MyMod import MyMod dans MyPak/__init__.py. Cependant, il trouve MyPak.MyMod dans sys.modules, ainsi il NE SERA PAS Reload MyMod bien que MyPak/MyMod.py ait été mis à jour. Et vous constaterez qu'aucun nouveau MyPak/MyMod.pyc n'est généré.

33
HongboZhu

Sous Python 3 uniquement, importez la fonction reload :

>>> from importlib import reload

Sur Python 2.x et 3.x, vous pouvez simplement appeler reload sur le module:

>>> import MyPak
>>> reload(MyPak)
>>> from MyPak import MyMod

Cependant, les instances de l'ancienne classe ne seront pas mises à jour (aucun code ne décrit simplement le mécanisme de mise à jour).

57
phihag

Il y a trois façons de résoudre ceci:

1. Utilisez import MyPak.MyMod au lieu de from MyPak import MyMod

Ensuite, vous pouvez écrire:

from importlib import reload  # If on Python 3
import MyPak.MyMod
reload(MyPak.MyMod)

et il fonctionne.

2. Utilisez IPython.lib.deepreload

from MyPak import MyMod
from IPython.lib.deepreload import reload
reload(MyPak)  # This should also reload all submodules

3. Utilisez chargement automatique magie

%load_ext autoreload
%autoreload 2
import MyPak.MyMod  # All changes to MyPak.MyMod will be loaded automatically
8
ostrokach

J'ai un fichier myfile.py qui contient une classe MyClass

Pour importer, il suffit de:

from myfile import MyClass
mc = MyClass()

Pour recharger:

import sys
del sys.modules['myfile']
from myfile import MyClass
modifiedmc = MyClass()

Ceci est très utile lors de la construction de modules . On peut les insérer dans une fonction et appeler simplement

def myreload():
   import sys
   del sys.modules['myfile']
   from myfile import MyClass
   modifiedmc = MyClass()
   global mc
   mc = modifiedmc
5
Sancho George

Vous pouvez utiliser une fonction magique:

%load_ext autoreload
%autoreload 2
from MyPak import MyMod
3

Cela fonctionne pour moi en utilisant python 3.5.2:

import importlib
importlib.reload(class)
from class import module
0
David Chen