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


69

如果导入的模块定义了属于同一个包的同名类,则由于父包的__init__.py,它将作为类而不是模块导入。有关详细信息,请在不同目录中查看不同的导入结果。在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 :(

我看不到打印的文字。更改未以某种方式应用。


1
CTRL+C$ pythonfrom MyPak import MyMod
雅各布

import MyPak.MyModreload(MyPak.MyMod)合作?
2011年

不,import MyPak.MyMod仍将MyPak.MyMod导入为
2011年

1
怎么样del MyMod,然后from MyPak import MyMod?您的程序包布局有点不寻常(使用MyPak / __ init__.py导入所有内容),但可以清除命名空间并允许您重新导入它。
Kirk Strauser 2011年

@Kirk Strauser:仍然没有运气。实际上,我之前已经做过。我很困惑。
2011年

Answers:


75

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

>>> from importlib import reload

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

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

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


刚刚测试。看来这也不会更新MyMod。我实际上有MyPak1.MyPak2.MyMod。但是我不认为这是原因:(
HongboZhu 2011年

4
在Python 3.3中不适用于我。您使用什么版本?
2014年

2
@AllTradesJack在Python 3上,您需要先导入重新加载:from importlib import reload
ostrokach

1
当我在python3.6中尝试时,这不适用于类。
乔什

1
@Josh您只能重新加载模块,而不能重新加载类本身。
powlo

43

我终于找到了答案:

import MyPak
from MyPak import MyMod

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

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

注意事项

  1. 执行del MyPakdel MyModdel MyPak.MyMod不能解决问题,因为它只是删除了名称绑定。Python仅搜索sys.modules以查看是否已导入模块。在sys.modules和globals()中的发布模块名称中查看讨论。

  2. 当重装MyPak,蟒蛇尝试执行线from MyMod import MyModMyPak/__init__.py。但是,它MyPak.MyMod在中找到sys.modules,因此即使已更新,也不会 重新加载。您会发现没有新的生成。MyModMyPak/MyMod.pyMyPak/MyMod.pyc


1
在3.3中,重新加载对我来说不是命令。您使用什么版本?
2014年

给定第2个警告,也许可以这样做:import MyPak.MyMod; reload(MyPak.MyMod); import MyPak; reload(MyPak); from MyPak import MyMod。除了这种方法无法扩展到更复杂的情况(就可读性而言)。建议的解决方案看起来更干净,因为它可以保证从环境中删除该模块。
Evgeni Sergeev

在3.3from imp import reloadreload()进入系统
Yona

在3.5import importlib之前我做过importlib.reload()
丹尼尔(Daniel)

16

有解决此问题的方法:

1.import MyPak.MyMod代替from MyPak import MyMod

然后您可以编写:

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

而且有效。

2.使用IPython.lib.deepreload

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

3.使用自动重装魔法

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

我最近几乎对自己的深度重装进行了编码...很高兴我没有浪费时间。这是一个超级有用的实用程序。
FinanceGuyThatCantCode

11

您可以使用魔术功能:

%load_ext autoreload
%autoreload 2
from MyPak import MyMod

它也适用于函数导入:

%load_ext autoreload
%autoreload 2
from anypythonfile import my_function

这个魔术函数可在Python 2.x(我在2.7+上测试)和Python 3.x(我在3.7上测试)中工作。


5

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

要导入,只需执行以下操作:

from myfile import MyClass
mc = MyClass()

重新加载:

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

这在构建模块时非常有用。可以将它们放在函数中,然后调用该函数

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

0

它适用于我使用python 3.5.2:

import importlib
importlib.reload(class)
from class import module
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.