Jos*_*del 5 python python-import python-2.7
如果我有一个像这样的目录结构:
\n\n.\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 pkg\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 A.py\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 B.py\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 C.py\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 test\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 script.py\n
Run Code Online (Sandbox Code Playgroud)\n\n其中script.py
包含:
import pkg.B\nimport pkg.A\n\nprint pkg.A.test()\n
Run Code Online (Sandbox Code Playgroud)\n\nA.py
:
import pkg.C\n\ndef test():\n return pkg.B.test()\n
Run Code Online (Sandbox Code Playgroud)\n\nB.py
:
def test():\n return \'AAAA\'\n
Run Code Online (Sandbox Code Playgroud)\n\nC.py
:
def test3():\n return \'C.test3\'\n
Run Code Online (Sandbox Code Playgroud)\n\n并且__init__.py
是空的。
如果A.py
导入pkg.C
,则代码有效。如果我注释掉该导入,则会失败并显示:
Traceback (most recent call last):\n File "pkg/test/script.py", line 9, in <module>\n print pkg.A.test()\n File "/Users/X/Desktop/importtest/pkg/A.py", line 4, in test\n return pkg.B.test()\nNameError: global name \'pkg\' is not defined\n
Run Code Online (Sandbox Code Playgroud)\n\n更改import pkg.C
为 just import pkg
,只要pkg.B
导入到 中也可以工作script.py
。
如果我注释掉pkg.B
from的导入,那么如果 I或inscript.py
没有什么区别,我会收到错误:import pkg
import pkg.C
A.py
Traceback (most recent call last):\n File "pkg/test/script.py", line 10, in <module>\n print pkg.A.test()\n File "/Users/X/Desktop/importtest/pkg/A.py", line 4, in test\n return pkg.B.test()\nAttributeError: \'module\' object has no attribute \'B\' \n
Run Code Online (Sandbox Code Playgroud)\n\n这是我期望的行为。
\n\n所以基本问题是,为什么pkg.B.test()
可以在A.py
if pkg.B
isn't imported 那里访问,ifpkg.B
被导入script.py
并A.py
导入其他子模块?
我仍然有点不清楚这里起作用的确切机制。非常感谢对描述导入逻辑的好文章的解释或指针。
\n这个问题有点老了,但我在遇到类似问题时偶然发现了它。这就是我所理解的正在发生的事情:
我们需要了解的第一件事是,模块仅加载一次!这意味着,例如,如果我们有:
X.py
:
import Z
import Y
blah blah
Run Code Online (Sandbox Code Playgroud)
Y.py
:
import Z
blah bloo
Run Code Online (Sandbox Code Playgroud)
运行X.py
会给我们带来以下结果:
import Y
)。import Z
是 module 中的第一行Y
,但 moduleZ
不会
再次加载。注意:无论如何,无论是否加载模块,模块的名称都会导入到当前命名空间中,使其可访问,但它们都引用相同的模块对象!。
当导入子模块时,例如pkg.A
,您实际上是在加载包pkg
__init__.py
模块,此外,还加载 A.py 模块。而且您正在做的是将子模块作为属性添加到包的 module 中。IE:
>>> import pkg
>>> hasattr(pkg, 'A')
False
Run Code Online (Sandbox Code Playgroud)
重述 Python 会话后:
>>> import pkg.A
>>> hasattr(pkg, 'A')
True
Run Code Online (Sandbox Code Playgroud)
因此,在执行script.py
时,会加载模块并将属性添加到其模块对象中。当导入时,由于已经加载,因此未加载,而是将名称导入到的名称空间中,同时引用中导入的同一模块对象。因为属性添加到该对象 (in )会成功,即使它是在 中执行的。import pkg.B
pkg
B
A.py
pkg.C
pkg
pkg
A.py
script.py
B
script.py
pkg.B.test
A.py
归档时间: |
|
查看次数: |
1173 次 |
最近记录: |