首页 > 解决方案 > 重新加载本地模块不起作用

问题描述

首先,我知道这之前已经发布过,但是 A)建议不起作用或 B)建议是从命名空间中手动删除模块并像往常一样重新导入它。

我有以下模块结构

basedir/
    pytools/
        __init__.py
        tools.py
    setup.py
    test.py

如果我在basedir, 并导入pytools并创建 class 的对象testcls。类的实际属性可在 中找到tools.pytestcls有一个名为的方法,它现在testfunc简单地打印出来:AAA

>>> import pytools
>>> test = pytools.testcls()
>>> test.testfunc()
AAA

假设我testfunc()改为现在 print out BBB。我这样做,并保存文件。然后我重新加载模块并重试,它没有打印出来BBB

>>> from importlib import reload
>>> reload(pytools)
>>> test = pytools.testcls()
>>> test.testfunc()
AAA

但是,如果我执行完全相同的过程,而是更改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

我真的不明白发生了什么,在这一点上真的很烦人。这也花费了我很多时间,但我现在更生气。

任何想法发生了什么?

版本:

蟒蛇:3.6.5

解释器:IPython,6.2.1

标签: pythonpython-3.xipythonpython-importlib

解决方案


让我们更一般地命名事物:

basedir/
    testpackage/
        __init__.py
        testmodule.py
    test.py

如果 testmodule.py 包含:

class TestClass:
    def test_method(self):
        print("AAA")

然后以下工作如您所愿:

>>> from testpackage import testmodule
>>> obj = testmodule.TestClass()
>>> obj.test_method()
DDD
>>> # === Edit ===
>>> from importlib import reload
>>> reload(testmodule)
>>> obj = testmodule.TestClass()
>>> obj.test_method()
EEE

但是,如果__init__.py有类似的东西:

from .testmodule import TestClass

如果您尝试导入(并重新加载)而不是模块,则会发生以下情况:

>>> import testpackage
>>> obj = testpackage.TestClass()
>>> obj.test_method()
EEE
>>> # === Edit ===
>>> from importlib import reload
>>> reload(testpackage)
>>> obj = testpackage.TestClass()
>>> obj.test_method()
EEE

(它没有改变)

请注意文档的以下部分:

如果一个模块使用 from ... import ... 从另一个模块导入对象,则为另一个模块调用 reload() 不会重新定义从它导入的对象——解决此问题的一种方法是重新执行 from 语句,另一种方法是使用 import 和限定名称 (module.name) 代替。

如果您要按此顺序重新加载模块包,它会再次按预期工作:

>>> import testpackage
>>> obj = testpackage.TestClass()
>>> obj.test_method()
HHH
>>> # === Edit ===
>>> from importlib import reload
>>> reload(testpackage.testmodule)
>>> reload(testpackage)
>>> obj = testpackage.TestClass()
>>> obj.test_method()
III

但这似乎很愚蠢且容易出错,只需使用第一个示例中的方法:

from testpackage import testmodule
...
reload(testmodule)
... 

推荐阅读