python中import的坑--同一模块中的同一对象,实例不同

来源:互联网 发布:qq输入法 linux 编辑:程序博客网 时间:2024/06/01 16:26

明明是同一模块下的同一对象,为何却能获取到不同的实例呢?

我在最近开发中遇到的一个坑,在模块中设置了单例,但是却并不能正确的访问到这个单例
这是由于python的import机制导致的

python在处理import时候大致过程如下 :

  1. 查找 sys.modules 是否有该模块,如果有直接导入
  2. 查找 sys.meta_path. meta_path 是一个 list,⾥面保存着一些 finder 对象,如果找到该module的话,就会返回一个finder对象。
  3. 检查⼀些隐式的finder对象,不同的python实现有不同的隐式finder,但是都会有 sys.path_hooks, sys.path_importer_cache 以及 sys.path。
  4. 抛出 ImportError。

我遇到的问题出在第3步,由于我们公司的框架在最开始的时候修改了sys.path,并且该目录下有一个__init__.py文件
这时候问题就产生了,有可能导致导入了两个不同的模块

你可能会有疑问,为什么会出现两个不同的模块呢?

其实是因为import的时候的方式不同
假设有一个模块 是One.Two
但是如果将One添加到sys.path
就会产生一种import Twoimport One.Two 都能导入这个模块的情况
但是这两种import方式生成的模块并不相同
import Two --会产生-> Two 模块
import One.Two -会产生--> One, One.Two 这两个模块
这个时候就很清晰了,因为import时的方式不同,会产生两个不同的模块
所以也就会导致两个单例的情况了

下面看代码

我的代码路径|PythonImportTest    |    |_____One    |       |    |       |______ __init__.py    |       |------ Two.py    |    |---- __init__.py#PythonImportTest.One.Two.pyg_Instance = []#PythonImportTest.__init__.pyimport sysg_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 = 2132336577992Module.g_Instance = 2132336607752

可以看到确实如同所说的一样,产生了两个不同的模块,并且其中的全局变量对象也不一样了

阅读全文
0 0
原创粉丝点击