Jam*_*ght 1 python ipython python-3.x python-importlib
首先,我知道这之前已经发布过,但是要么 A)建议不起作用,要么 B)建议从命名空间中手动删除模块并像平常一样重新导入它。
我有以下模块结构
basedir/
pytools/
__init__.py
tools.py
setup.py
test.py
Run Code Online (Sandbox Code Playgroud)
如果我在basedir
,并导入pytools
并创建一个 类 的对象testcls
。该类的实际属性可在 中找到tools.py
。testcls
有一个名为的方法,它现在testfunc
就简单地打印出来:AAA
>>> import pytools
>>> test = pytools.testcls()
>>> test.testfunc()
AAA
Run Code Online (Sandbox Code Playgroud)
假设我更改testfunc()
为现在打印出来BBB
。我这样做,并保存文件。然后我重新加载模块并重试,它没有打印出来BBB
:
>>> from importlib import reload
>>> reload(pytools)
>>> test = pytools.testcls()
>>> test.testfunc()
AAA
Run Code Online (Sandbox Code Playgroud)
但是,如果我执行完全相同的过程,但改为更改test.py
,将该文件作为模块导入,编辑其中的函数,然后重新加载它,它的行为将按预期进行:
>>> import test
>>> testvariable = test.testcls()
>>> testvariable.testfunc2()
AAA
# Change the function here
>>> from importlib import reload
>>> reload(test)
>>> testvariable = test.testcls()
>>> testvariable.testfunc2()
BBB
Run Code Online (Sandbox Code Playgroud)
我真的不明白发生了什么事,这让我很恼火。这也花费了我很多时间,但我现在更恼火。
有什么想法吗?
蟒蛇:3.6.5
解释器:IPython,6.2.1
让我们更笼统地命名一些东西:
\n\nbasedir/\n testpackage/\n __init__.py\n testmodule.py\n test.py\n
Run Code Online (Sandbox Code Playgroud)\n\n如果 testmodule.py 包含:
\n\nclass TestClass:\n def test_method(self):\n print("AAA")\n
Run Code Online (Sandbox Code Playgroud)\n\n然后,以下内容将按您的预期工作:
\n\n>>> from testpackage import testmodule\n>>> obj = testmodule.TestClass()\n>>> obj.test_method()\nDDD\n>>> # === Edit ===\n>>> from importlib import reload\n>>> reload(testmodule)\n>>> obj = testmodule.TestClass()\n>>> obj.test_method()\nEEE\n
Run Code Online (Sandbox Code Playgroud)\n\n但是,如果__init__.py
有类似的东西:
from .testmodule import TestClass\n
Run Code Online (Sandbox Code Playgroud)\n\n然后您尝试导入(并重新加载)包而不是模块时,会发生以下情况:
\n\n>>> import testpackage\n>>> obj = testpackage.TestClass()\n>>> obj.test_method()\nEEE\n>>> # === Edit ===\n>>> from importlib import reload\n>>> reload(testpackage)\n>>> obj = testpackage.TestClass()\n>>> obj.test_method()\nEEE\n
Run Code Online (Sandbox Code Playgroud)\n\n(不变)
\n\n请注意文档的以下部分:
\n\n\n\n\n如果一个模块使用 from \xe2\x80\xa6 import \xe2\x80\xa6 从另一个模块导入对象,则为另一个模块调用 reload() 不会重新定义从 \xe2\x80\x94 导入的对象一种是重新执行from语句,另一种是使用import和限定名(module.name)代替。
\n
如果您要按顺序重新加载模块和包,它会再次按您的预期工作:
\n\n>>> import testpackage\n>>> obj = testpackage.TestClass()\n>>> obj.test_method()\nHHH\n>>> # === Edit ===\n>>> from importlib import reload\n>>> reload(testpackage.testmodule)\n>>> reload(testpackage)\n>>> obj = testpackage.TestClass()\n>>> obj.test_method()\nIII\n
Run Code Online (Sandbox Code Playgroud)\n\n但这看起来很愚蠢而且容易出错,只需使用第一个示例中的方法即可:
\n\nfrom testpackage import testmodule\n...\nreload(testmodule)\n... \n
Run Code Online (Sandbox Code Playgroud)\n