我正在尝试开发和测试包foo.bar。我有以下目录布局:
myproject
setup.py (for package foo.bar)
foo
bar
__init__.py
...
tests
main.py
test_something.py
在test_something.py中,我想导入foo.bar的本地副本,理想情况下只需使用' import foo.bar'。
在main.py中我有:
import os
import sys
sys.path.append(
os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import test_something
然而,我收到错误:
File "./tests/main.py", line 22, in <module>
import test_something
File "/myproject/tests/test_something.py", line 28, in <module>
import foo.bar
ImportError: No module named bar
是否可以这样做?
答案 0 :(得分:1)
如果您希望foo
被视为一个包,则需要在__init__.py
目录下直接有foo
,它可以为空,但文件需要在那里。否则Python不会将foo
视为一个包,你不能这样做 -
import foo.bar
如评论中所述 -
无论如何我不希望foo成为一个包,我希望foo.bar成为包。
这不是直接可能的,因为除非import foo.bar
是Python包(或下面解释的命名空间包),否则不能foo
。
此处唯一的另一种选择是使用 -
将foo
文件夹直接添加到sys.path
sys.path.append(
os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'foo')))
然后你必须将其导入为 -
import bar
如果您使用的是 Python 3.3 + ,那么您可以使用namespace packages
,并且可以导入foo.bar
,而无需在__init__.py
内定义foo
1}}。
这在 - PEP 0420中有很好的解释,根据规范,python包/模块(来自3.3 +)的新的编码过程是 -
在导入处理期间,导入机制将继续迭代父路径中的每个目录,就像在Python 3.2中一样。在寻找名为“foo”的模块或包时,对于父路径中的每个目录:
- 如果找到
<directory>/foo/__init__.py
,则会导入并返回常规包。- 如果没有,但找到
<directory>/foo.{py,pyc,so,pyd}
,则会导入并返回模块。扩展名的确切列表因平台而异,是否指定了-O标志。这里的清单具有代表性。- 如果没有,但找到
<directory>/foo
并且是目录,则会记录该目录,并继续扫描父路径中的下一个目录。- 否则,扫描将继续执行父路径中的下一个目录。
如果扫描完成而未返回模块或包,并且至少记录了一个目录,则会创建命名空间包。新的命名空间包:
- 将
__path__
属性设置为扫描期间找到并记录的可迭代路径字符串。- 没有
__file__
属性。