来自相对包的未知python导入行为

来自相对包的未知python导入行为,python,import,Python,Import,我偶然发现了一些奇怪的python(2.7)导入行为,虽然很容易解决,但让我摸不着头脑 给定以下文件夹结构: test/ __init__.py x.py package/ __init__.py x.py 其中test/package/_init__.py包含以下内容 from .. import x print x from .x import hello print x print x.hello hello = 1 test/

我偶然发现了一些奇怪的python(2.7)导入行为,虽然很容易解决,但让我摸不着头脑

给定以下文件夹结构:

test/
    __init__.py
    x.py
    package/
        __init__.py
        x.py
其中test/package/_init__.py包含以下内容

from .. import x
print x
from .x import hello
print x
print x.hello
hello = 1
test/package/x.py包含以下内容

from .. import x
print x
from .x import hello
print x
print x.hello
hello = 1
为什么从REPL运行
import test.package
会导致以下输出

<module 'test.x' from 'test/x.pyc'>
<module 'test.package.x' from 'test/package/x.pyc'>
1

1.
我本来希望
x
引用顶级
x
模块,但是第二次导入所做的是导入整个本地
x
模块(而不是像我预期的那样仅导入
hello
),实际上是对第一次导入的践踏


有人能在这里解释导入的机制吗?

来自.x导入名称的
意识到
test.package.x
需要是一个模块。然后检查
sys.modules
中的相应条目;如果在那里找到它,则将
sys.modules['test.package.x'].hello
导入调用模块

但是,如果
sys.modules['test.package.x']
尚不存在,则加载该模块;作为加载
sys.modules['test.package']]的最后一步,x
被设置为指向新加载的模块,即使您没有明确要求它。因此,第二个导入将覆盖第一个导入的名称

否则,这是故意的

import foo.bar.baz
foo.bar.baz.x()

不能互换


我无法在Python 2文档中找到关于此行为的良好文档,但在本例中基本相同:

当使用任何机制(例如
importlib
API、
import
import
-
-from
语句或内置的
\uu import\uuu()
)加载子模块时,会在父模块的命名空间中放置到子模块对象的绑定。例如,如果包
spam
具有子模块
foo
,则导入
spam.foo
后,
spam
将具有绑定到子模块的属性
foo

[……]

不变的保持是,如果您有
sys.modules['spam']
sys.modules['spam.foo']
(正如您在上述导入之后所做的那样),则后者必须显示为前者的
foo
属性


是什么让你认为第一次导入带来了一个
x
,第二次导入用另一个
x
?在你的代码或描述中没有任何东西可以测试或演示这一点right@AnttiHaapala他可能是,但他没有实际测试(例如,在第二次导入之前和之后通过
print x
)可能重复的abarnert,当我更改代码以在第二次导入之前添加打印时,它会首先突出显示导入的预期模块:其次: