使用nose进行测试的Python导入 - 处理当前包以上模块导入的最佳实践是什么
这个问题经常以不同的形式被提出来,通常会得到一些“哈哈,你没搞明白”的回答。我觉得这是因为大家(包括我自己)在尝试用一种常识性的场景来实现,但解决方案并不明显(如果你之前没做过的话)。
我希望能得到一个“让问题迎刃而解”的答案。
给定
project/
__init__.py
/code
__init__.py
sut.py
/tests
__init__.py
test_sut.py
测试文件 tests_sut.py 开始的地方:
import code.sut
在根目录下运行 nosetests 会得到:
ImportError: No module named code.sut
尝试过的方法:
a) 使用相对路径
from ..code import sut
b) 将项目的根目录添加到 PYTHONPATH
c) 在每个测试模块开始时,使用
sys.path.append
在导入之前添加 .. 路径。
d) 记得在运行测试之前,
setup.py
对项目进行一次安装,把模块放到 site-packages 里。
所以要求是测试文件要放在测试包的根目录下,并且能够访问到项目。以上每种方法对我来说都感觉不“自然”,而且有些方法还挺麻烦的!
在 Java 中,这个问题很好解决,因为你的构建工具或 IDE 会把所有的类放到类路径上。也许问题在于我对 Python 期待了“魔法”?我注意到在 Flask 这个网页框架的测试中,选项 d) 似乎是更受欢迎的选择。
无论如何,下面的建议如果能推荐一个更好的解决方案,就能消除我心中的“奇怪感”。
3 个回答
我知道已经有一个答案被认可了,但我觉得分享其他选择也是很有意义的 :)
有一个叫做 nose-pathmunge 的工具,它可以让你在运行 nosestests
时,控制 sys.path
的设置。
我也遇到过同样的问题,后来在一个相关的问题中找到了一条答案,对我有帮助。
只需要把项目根目录下的 __init__.py 文件删除就可以了。
你已经很好地回答了自己的问题。
D(安装到系统位置)是分发代码时的首选。我通常使用C(修改sys.path),因为我不想在系统范围内安装我数百个自定义库。从理论上讲,A(相对导入)似乎更好,但在某些情况下会失败。
B(PYTHONPATH)在我看来真的不合适,主要是用于测试。
这基本上总结了所有的选项。你喜欢的选项(Python神奇地知道去哪里找)其实并不是一个可行的解决方案,因为它可能导致不可预测的结果,比如自动找到与项目无关的库。
在我看来,最好的做法是在你的程序的入口点放置以下内容:
import sys, os
sys.path = [os.path.abspath(os.path.dirname(__file__))] + sys.path