Python reload()没有重新加载类实现?

时间:2017-02-01 19:32:11

标签: python python-2.7

我有一个类似如下的模块结构:

.
└── testmodule
    ├── __init__.py
    └── submodule
        ├── __init__.py
        └── implementation.py

2 directories, 3 files

以下是每个文件的内容

# testmodule/__init__.py
import submodule
# testmodule/submodule/__init__.py
from implementation import *
# testmodule/submodule/implementation.py
class Car(object):
    def __init__(self):
        self.doors = 2
        self.color = 'red'

为什么课程实施没有"重新加载"当我在下面的测试中使用reload()时?

Python 2.7.12 (default, Oct 11 2016, 05:24:00)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import testmodule
>>> car = testmodule.submodule.Car()
>>> car.doors
2
>>> # I edit the file and change self.doors = 2 to self.doors = 4
>>> reload(testmodule)
<module 'testmodule' from 'testmodule/__init__.pyc'>
>>> car = testmodule.submodule.Car()
>>> car.doors
2
>>> # no more edits made before the Python REPL is restarted

me@laptop # python
Python 2.7.12 (default, Oct 11 2016, 05:24:00)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import testmodule
>>> car = testmodule.submodule.Car()
>>> car.doors
4

更新

根据@ wim的逻辑,我将不得不重新加载testmodule.submodule.implementation,然后重新加载testmodule.submodule以使这个&#34;工作&#34;,事实确实如此。见这些测试:

Python 2.7.12 (default, Oct 11 2016, 05:24:00)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import testmodule
>>> c = testmodule.submodule.Car()
>>> c.doors
2
>>> # I edit the file and change self.doors = 2 to self.doors = 4
>>> reload(testmodule.submodule.implementation)
<module 'testmodule.submodule.implementation' from 'testmodule/submodule/implementation.py'>
>>> c = testmodule.submodule.Car()
>>> c.doors
2
>>> reload(testmodule.submodule)
<module 'testmodule.submodule' from 'testmodule/submodule/__init__.pyc'>
>>> c = testmodule.submodule.Car()
>>> c.doors
4

me@laptop # python
Python 2.7.12 (default, Oct 11 2016, 05:24:00)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import testmodule
>>> c = testmodule.submodule.Car()
>>> c.doors
2
>>> # I edit the file and change self.doors = 2 to self.doors = 4
>>> reload(testmodule.submodule)
<module 'testmodule.submodule' from 'testmodule/submodule/__init__.pyc'>
>>> c = testmodule.submodule.Car()
>>> c.doors
2
>>> reload(testmodule.submodule.implementation)
<module 'testmodule.submodule.implementation' from 'testmodule/submodule/implementation.py'>
>>> c = testmodule.submodule.Car()
>>> c.doors
2
>>> reload(testmodule.submodule)
<module 'testmodule.submodule' from 'testmodule/submodule/__init__.pyc'>
>>> c = testmodule.submodule.Car()
>>> c.doors
4

1 个答案:

答案 0 :(得分:4)

TL; DR表示重新加载的预期行为。

为什么会这样?

导入testmodule实际上会将子包加载到sys.modules

>>> import testmodule
>>> [m for m in sys.modules if m.startswith('testmodule')]
['testmodule.submodule', 'testmodule.submodule.implementation', 'testmodule']

现在,当您重新加载testmodule时,它将直接获取testmodule实施中的更改 - 即testmodule/__init__.py中更改的所有行。

但是,您没有更改那里的任何行,submodule包含引用的testmodule名称仍将指向旧的submodule

基本上,元回答是你高估了“重新加载”对事物的敏感程度。你可以实现一个挂钩到子包中的深度重载,但是很难做到正确,我建议你不要打扰。

你能做些什么?

如果你有兴趣,IPython会朝这个方向做一些尝试:

# Python 2
import __builtin__
from IPython.lib import deepreload
__builtin__.reload = deepreload.reload

(有关详细信息,请参阅IPython.lib.deepreload。)