如何在python shell中重新加载一个类?

Hon*_*Zhu 63 python ipython

如果我导入定义属于某个包的同名类的模块,则由于父包的__init__.py而导致它作为Class而不是Module导入.有关详细信息,请参阅不同目录的不同导入结 在Python shell或ipython shell中,如果我这样做

from MyPak import MyMod

MyModule总是作为Class导入,因此我无法重新加载它(reload()仅适用于模块).跑

from MyPak import MyMod

再似乎没有更新类定义.任何人都可以建议一种方法来更新python shell中的类?

PS.无需重新启动python解释器.

pps.万一你手头有代码并想测试它:我实际上是在谈论BioPython,我正在研究Bio.PDB.PDBParser.我有一个ipython shell(v0.10)并编辑PDBParser.py.只是无法在ipython中重新加载它.

所以这就是我所做的:

# 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 :(
Run Code Online (Sandbox Code Playgroud)

我看不到印刷文字了.这些变化没有以某种方式应用.

phi*_*hag 65

仅在Python 3上,导入reload函数:

>>> from importlib import reload
Run Code Online (Sandbox Code Playgroud)

在Python 2.x和3.x上,您可以简单地调用reload模块:

>>> import MyPak
>>> reload(MyPak)
>>> from MyPak import MyMod
Run Code Online (Sandbox Code Playgroud)

但是,旧类的实例不会更新(根本没有描述更新机制的代码).

  • 在Python 3.3中不适用于我.你用的是什么版本? (4认同)
  • 当我在 python3.6 中尝试时,这对类不起作用。 (3认同)
  • @AllTradesJack在Python 3上,您需要先导入重新加载:`from importlib import reload`. (2认同)
  • @Josh你只能重新加载模块,而不能重新加载类本身。 (2认同)

Hon*_*Zhu 41

我终于找到了答案:

import MyPak
from MyPak import MyMod
Run Code Online (Sandbox Code Playgroud)

编辑后MyPak/MyMod.py的文件,重新装入类MyMod文件中MyMod.py,需要

import sys
del sys.modules['MyPak.MyMod'] 
reload(MyPak)
from MyPak import MyMod
Run Code Online (Sandbox Code Playgroud)

警告:

  1. 执行del MyPak或者del MyMod还是del MyPak.MyMod没有解决问题,因为它只是删除名称绑定.Python仅搜索sys.modules模块是否已导入.查看sys.modules和globals()中 post 模块名称中的讨论.

  2. 当重装MyPak,蟒蛇尝试执行线from MyMod import MyModMyPak/__init__.py.但是,它找到MyPak.MyModsys.modules,因此虽然已经更新,但它不会 重新加载.你会发现没有新的东西产生.MyModMyPak/MyMod.pyMyPak/MyMod.pyc

  • 在 3.3 中,重新加载不被识别为我的命令。你用的是什么版本? (2认同)

ost*_*ach 11

有办法解决这个问题:

1.使用import MyPak.MyMod而不是from MyPak import MyMod

然后你可以写:

from importlib import reload  # If on Python 3
import MyPak.MyMod
reload(MyPak.MyMod)
Run Code Online (Sandbox Code Playgroud)

它的工作原理.

2.使用IPython.lib.deepreload

from MyPak import MyMod
from IPython.lib.deepreload import reload
reload(MyPak)  # This should also reload all submodules
Run Code Online (Sandbox Code Playgroud)

3.使用自动加载魔法

%load_ext autoreload
%autoreload 2
import MyPak.MyMod  # All changes to MyPak.MyMod will be loaded automatically
Run Code Online (Sandbox Code Playgroud)


Sel*_*maz 5

您可以使用魔术功能:

%load_ext autoreload
%autoreload 2
from MyPak import MyMod
Run Code Online (Sandbox Code Playgroud)


小智 5

我有一个myfile.py文件,其中包含一个类MyClass

要导入只需:

from myfile import MyClass
mc = MyClass()
Run Code Online (Sandbox Code Playgroud)

要重新加载:

import sys
del sys.modules['myfile']
from myfile import MyClass
modifiedmc = MyClass()
Run Code Online (Sandbox Code Playgroud)

这在构建模块时非常有用.一个人可以将这些放在一个函数中,然后调用该函数

def myreload():
   import sys
   del sys.modules['myfile']
   from myfile import MyClass
   modifiedmc = MyClass()
   global mc
   mc = modifiedmc
Run Code Online (Sandbox Code Playgroud)