明明是同一模块下的同一对象,为何却能获取到不同的实例呢?
我在最近开发中遇到的一个坑,在模块中设置了单例,但是却并不能正确的访问到这个单例
这是由于python的import机制导致的
python在处理import时候大致过程如下 :
- 查找 sys.modules 是否有该模块,如果有直接导入
- 查找 sys.meta_path. meta_path 是一个 list,⾥面保存着一些 finder 对象,如果找到该module的话,就会返回一个finder对象。
- 检查⼀些隐式的finder对象,不同的python实现有不同的隐式finder,但是都会有 sys.path_hooks, sys.path_importer_cache 以及 sys.path。
- 抛出 ImportError。
我遇到的问题出在第3步,由于我们公司的框架在最开始的时候修改了sys.path
,并且该目录下有一个__init__.py
文件
这时候问题就产生了,有可能导致导入了两个不同的模块
你可能会有疑问,为什么会出现两个不同的模块呢?
其实是因为import
的时候的方式不同
假设有一个模块 是One.Two
但是如果将One
添加到sys.path
中
就会产生一种import Two
和 import One.Two
都能导入这个模块的情况
但是这两种import方式生成的模块并不相同
import Two --会产生-> Two 模块
import One.Two -会产生--> One, One.Two 这两个模块
这个时候就很清晰了,因为import
时的方式不同,会产生两个不同的模块
所以也就会导致两个单例的情况了
下面看代码
我的代码路径
|PythonImportTest
|
|_____One
| |
| |______ __init__.py
| |------ Two.py
|
|---- __init__.py
#PythonImportTest.One.Two.py
g_Instance = []
#PythonImportTest.__init__.py
import sys
g_SysModulesCacheSet = set(sys.modules)
sys.path.append('One')
if __name__ == '__main__':
import Two
import One.Two
print("-" * 20, "sys.module print begin", "-"*20)
print(set(sys.modules) - g_SysModulesCacheSet)
print("-" * 20, "sys.module print end", "-"*20)
print('One.Module.g_Instance =', id(One.Two.g_Instance))
print("Module.g_Instance =", id(Two.g_Instance))
输出结果
-------------------- sys.module print begin --------------------
{'Two', 'One', 'One.Two'}
-------------------- sys.module print end --------------------
One.Module.g_Instance = 2132336577992
Module.g_Instance = 2132336607752
可以看到确实如同所说的一样,产生了两个不同的模块,并且其中的全局变量对象也不一样了