重新加载通过 'from X import Y' 导入的组件 Y

137 投票
9 回答
67246 浏览
提问于 2025-04-15 16:03

在Python中,当我在解释器中用 import X 导入了一个模块X后,如果外面的这个模块发生了变化,我可以用 reload(X) 来重新加载这个模块。这样,更新的内容就可以在我的解释器会话中使用了。

我想知道,如果我通过 from X import Y 从模块X中导入了一个组件Y,这种情况是否也可以重新加载。

直接用 reload Y 是不行的,因为 Y 不是一个独立的模块,而只是模块中的一个组件(在这个例子中是一个类)。

那么,是否有办法在不退出解释器会话的情况下,重新加载模块中的某个单独组件,而不需要重新导入整个模块呢?

为了更清楚,这个问题是关于从模块X中导入一个类或函数Y,并在发生变化时重新加载,而不是从包X中导入模块Y。

9 个回答

29

在编程中,有时候我们需要处理一些数据,比如从一个地方获取数据,然后在程序里使用它。这个过程可能会涉及到很多步骤,比如连接到数据库、查询数据、处理数据等等。

想象一下,你在一个图书馆里找书。首先,你需要知道书的位置(这就像连接到数据库),然后你去找那本书(这就像查询数据),最后你把书拿到手里,可能还要翻阅几页(这就是处理数据)。

在这个过程中,可能会遇到一些问题,比如找不到书,或者书被借走了。这些问题就像编程中可能出现的错误,我们需要想办法解决它们。

总之,处理数据就像在图书馆找书一样,需要耐心和技巧,才能顺利完成任务。

from modulename import func

import importlib, sys
importlib.reload(sys.modules['modulename'])
from modulename import func
144

回答

根据我的测试,那个推荐简单使用 reload(X) 的答案并不好用。

从我了解到的情况来看,正确的答案是:

from importlib import reload # python 2.7 does not require this
import X
reload( X )
from X import Y

测试

我的测试是这样的(使用 Python 2.6.5 和 bpython 0.9.5.2)

X.py 文件内容:

def Y():
    print "Test 1"

bpython 的内容:

>>> from X import Y
>>> print Y()
Test 1
>>> # Edit X.py to say "Test 2"
>>> print Y()
Test 1
>>> reload( X )  # doesn't work because X not imported yet
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'X' is not defined
>>> import X
>>> print Y()
Test 1
>>> print X.Y()
Test 1
>>> reload( X ) # No effect on previous "from" statements
>>> print Y()
Test 1
>>> print X.Y() # first one that indicates refresh
Test 2
>>> from X import Y
>>> print Y()
Test 2 
>>> # Finally get what we were after
56

如果Y是一个模块(而X是一个包),那么使用reload(Y)是没问题的——否则,你就会明白为什么好的Python风格指南(比如我工作的地方)会说绝对不要导入任何东西除了模块。这是很多好理由中的一个——但人们还是一直直接导入函数和类,不管我怎么解释这不是个好主意;-)。

撰写回答