在python3.7-buster docker容器上运行Python 3.7.9
这是我的问题的一个基本例子
首先,我导入json
模块并验证它是否包含作为属性的decoder
模块:
>>> import json, importlib
>>> json.decoder
<module 'json.decoder' from '/usr/local/lib/python3.7/json/decoder.py'>
然后,我将该属性设置为None并验证:
>>> json.__dict__['decoder'] = None
>>> json.decoder # None's repr is blank
尝试重新加载模块,重新检查json.decoder
状态。我希望它再次成为一个模块,但我发现的是:
>>> importlib.reload(json)
<module 'json' from '/usr/local/lib/python3.7/json/__init__.py'>
>>> json.decoder # None's repr is blank
OK,我可以直接导入解码器吗?不,它只是返回已经加载的模块的值。(这并非完全出乎意料。)
>>> from json import decoder as new_decoder
>>> new_decoder # None's repr is blank
OK,我注意到importlib.reload()
返回一个模块。如果我设置模块标识符等于函数调用呢?
>>> json = importlib.reload(json)
>>> json.decoder # None's repr is blank
下面是Python文档中有关重载的一段代码:
当reload()被执行时:
Python模块的代码被重新编译并重新执行模块级代码,定义一组新的对象,这些对象被绑定到模块字典中的名称,通过重用加载器加载模块。扩展模块的init函数不会被第二次调用。...模块命名空间中的名称被更新为指向任何新的或更改的对象
这似乎准确地描述了我所期望的行为,但不是我所遇到的。这是怎么回事?
重新执行json
包的代码只是并不重新分配json.decoder
。在json
包的__init__.py
中没有任何东西可以做到这一点。
json
包的__init__.py
包含以下行:
from .decoder import JSONDecoder, JSONDecodeError
第一次运行这一行(在第一次导入json
时),json.decoder
子模块被初始化,并且作为初始化的一部分,对该子模块的引用被设置为json
模块对象的decoder
属性。
当您重新加载json
时,这一行被重新执行,但是json.decoder
子模块已经被初始化,不需要再次初始化。
json.decoder
未被重新分配。一般来说,你不应该期望重新加载一个模块会使它处于任何一种正常或有用的状态。模块重载有很多奇怪和微妙的问题,比如创建"邪恶的双胞胎";类,不更新任何从模块导入的from
,不能很好地与扩展模块,等等。