我创建了一个简单的包来说明这个问题。以下是文件结构:
pypkg
├── __init__.py
├── __main__.py
├── sub_a
│ └── __init__.py
└── sub_b
└── __init__.py
sub_a
有一个函数foo
:
# sub_a/__init__.py
def foo():
print 'foo'
sub_b
有一个函数foobar
调用foo
:
# sub_b/__init__.py
from sub_a import foo
def foobar():
foo()
print 'bar'
在主文件中,我导入foobar
没有问题:
# __main__.py
from sub_b import foobar
if __name__ == '__main__':
foobar()
如果我用python pypkg
运行包,它就可以正常工作。当我尝试从外部使用foobar
时,问题就开始了。 我在路径中添加了pypkg
,但是当我尝试导入foobar
时,它引发了ImportError
异常。这是一个演示:
In [1]: from pypkg.sub_b import foobar
---------------------------------------------------------------------------
ImportError Traceback (most recent call last)
<ipython-input-1-37682ecaec63> in <module>()
----> 1 from pypkg.sub_b import foobar
[...]/pypkg/sub_b/__init__.py in <module>()
----> 1 from sub_a import foo
2
3 def foobar():
4 foo()
5 print 'bar'
ImportError: No module named sub_a
发生ImportError
不是因为它找不到sub_b
- 它可以 - 问题发生是因为包无法导入自己的"邻居子包"。这就引出了一个问题:如何正确地从外部导入foobar
?
我对这个主题进行了广泛的研究,关于SO的绝大多数问题都是没有放置__init__.py
文件的人,请注意这不是这里的问题。
问题是__main__.py
被视为脚本,而不是pypkg
模块的一部分。从__main__.py
的角度来看,sub_a
和sub_b
被视为两个不共享公共父模块的模块。如果您将布局更改为
pypkg
├── __main__.py
└── pkg
├── __init__.py
├── sub_a
│ └── __init__.py
└── sub_b
└── __init__.py
sub_a
和 sub_b
将共享公共父模块pkg
,即使从 __main__.py
调用也是如此。这允许您在sub_b/__init__.py
中执行相对导入:
from ..sub_a import foo
在 Python 2 下,您可能需要添加以下行
from __future__ import absolute_import
python会根据你的工作路径计算路径。
因此,您可以选择是使用具有固定工作路径的绝对模块路径还是使用具有可变工作路径的相对模块路径。