'importlib.reload' 不会替换模块的 '__dict__' 中的对象



在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,不能很好地与扩展模块,等等。

最新更新