我在构建python项目时遇到了一些问题。目前它是同一文件夹中的一堆文件。我试图像
那样构建它proj/
__init__.py
foo.py
...
bar/
__init__.py
foobar.py
...
tests/
foo_test.py
foobar_test.py
...
问题是我无法从内部目录导入外部目录中的模块。这对测试尤其恼人。
我已阅读有关相对导入的PEP 328和有关主模块相对导入的PEP 366。但是这两种方法都要求基础包在我的PYTHONPATH中。实际上我得到了以下错误
ValueError:在非包中尝试相对导入。
所以我在测试文件
之上添加了以下样板代码import os, sys
sys.path.append(os.path.join(os.getcwd(), os.path.pardir))
我仍然得到同样的错误。
的正确方法是什么? 编辑根据评论中的要求,我添加了失败的示例导入(在文件foo_test.py
中)
import os, sys
sys.path.append(os.path.join(os.getcwd(), os.path.pardir))
from ..foo import Foo
答案 0 :(得分:12)
使用-m
开关运行代码时,当前目录将添加到sys.path
。因此,运行测试的最简单方法是使用命令:
proj
的父目录
python -m proj.tests.foo_test
为了实现这一目标,您需要在测试目录中包含一个__init__.py
文件,以便将测试正确识别为包的一部分。
答案 1 :(得分:5)
我希望尽可能使用完整的proj.NAME
包前缀导入模块。这是Google Python styleguide推荐的方法。
允许您保留包结构,使用完整包路径并继续开发的一个选项是使用virtualenv并将项目置于开发模式。您的项目setup.py
需要使用setuptools
而不是distutils
来获取develop
命令。
这样可以避免上面的sys.path.append
内容:
% virtualenv ~/virt
% . ~/virt/bin/activate
(virt)~% cd ~/myproject
(virt)~/myproject% python setup.py develop
(virt)~/myproject% python tests/foo_test.py
foo_test.py
使用的地方:
from proj.foo import Foo
现在,当您从virtualenv中运行python
时,PYTHONPATH
将指向项目中的所有软件包。您可以创建一个较短的shell别名来输入您的virtualenv,而无需每次都输入. ~/virt/bin/activate
。