Python 3.6中importlib.reload是否应恢复已删除的模块属性?
Python 3.6模块重载后属性未恢复的异常行为分析
最近我在研究两个相关的模块重载问题时,发现Python 3.6出现了和Python 2.7、3.4不一致的异常行为:
- 原本在模块初始化或重载时应被自动填充的模块属性,在使用
del语句删除该属性的本地名称后,再次重载模块时这个属性居然没有恢复。
为了搞清楚问题根源,我已经开始深入探究importlib模块的相关实现细节——毕竟Python 3之后模块的导入与重载逻辑由importlib主导,很可能是3.6版本对这部分逻辑做了变动,才导致删除本地属性后重载无法重新生成对应模块属性。
举个直观的测试场景就能复现这个差异:
- 定义测试模块
test_mod.py,初始化属性foo = "bar" - 主脚本导入该模块,打印
test_mod.foo可正常输出"bar" - 执行
del test_mod.foo删除属性,此时访问会触发属性不存在的报错 - 调用
importlib.reload(test_mod)重载模块,在Python 2.7/3.4中foo会恢复为"bar",但Python 3.6里依然无法找到该属性
这种差异大概率和Python 3.6对模块命名空间的处理优化有关,或是reload函数在处理已删除属性时的逻辑变更。后续我打算重点对比不同版本importlib._bootstrap中的重载相关代码,定位导致行为变化的具体原因。
内容的提问来源于stack exchange,提问作者ely




