Python包导入混乱
如果我有一个目录结构,如:
. └── pkg ├── A.py ├── B.py ├── C.py ├── __init__.py └── test └── script.py 其中script.py包含: import pkg.B import pkg.A print pkg.A.test() A.py: import pkg.C def test(): return pkg.B.test() B.py: def test(): return 'AAAA' C.py: def test3(): return 'C.test3' 并且__init__.py为空. 如果A.py导入pkg.C,则代码可以正常工作.如果我注释掉那个导入,那么它失败了: Traceback (most recent call last): File "pkg/test/script.py",line 9,in <module> print pkg.A.test() File "/Users/X/Desktop/importtest/pkg/A.py",line 4,in test return pkg.B.test() NameError: global name 'pkg' is not defined 将import pkg.C更改为只导入pkg,只要在script.py中导入pkg.B,也可以正常工作. 如果我从script.py注释掉pkg.B的导入,那么如果我在A.py中导入pkg或导入pkg.C它没有什么区别,我收到一个错误: Traceback (most recent call last): File "pkg/test/script.py",line 10,in test return pkg.B.test() AttributeError: 'module' object has no attribute 'B' 这是我期望的行为. 所以基本的问题是,为什么pkg.B.test()可以在A.py中访问,如果pkg.B没有在那里导入,如果在script.py中导入了pkg.B而且A.py导入了其他子模块? 关于这里工作的确切机制我还有点不清楚.对于描述导入逻辑的好文章的解释或指示将是最受欢迎的. 解决方法
这个问题有点陈旧,但在遇到类似问题时我偶然发现了它.这就是我所理解的情况:
模块导入一次 我们首先需要了解的是,modules are loaded only once!这意味着,例如,如果我们有: X.py: import Z import Y blah blah Y.py: import Z blah bloo 运行X.py将为我们提供以下内容: >模块Z将在第一行加载. 注意:无论如何,无论是否加载模块,模块的名称都会导入到当前名称空间中,使其可访问但它们都引用相同的模块对象!! 导入子模块 导入子模块(例如pkg.A)时,实际上是在加载包pkg __init__.py模块,另外还要加载A.py模块.但是你正在做的是将子模块作为属性添加到包的模块中.即: >>> import pkg >>> hasattr(pkg,'A') False 重新启动Python会话后: >>> import pkg.A >>> hasattr(pkg,'A') True 把碎片放在一起 因此,在执行导入pkg.B时的script.py中,将加载pkg模块,并将属性B添加到其“模块对象”中.当A.py导入pkg.C时,pkg没有加载,因为它已经加载了,而是将名称pkg导入到A.py的命名空间中,同时引用在script.py中导入的同一模块对象.因为属性B已添加到该对象(在script.py中),pkg.B.test成功,即使它在A.py中执行也是如此. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |