我有一个包含以下存储库结构的python库:
repobase
|- mylibrary
| |- __init__.py
|- tests
|- test_mylibrary.py
到目前为止,可以通过调用repobase目录中的py.test
来完成测试。然后 test_mylibrary.py 中的import mylibrary
使用 repobase / mylibrary 中的本地代码。
现在,我已经扩展了库以使用编译代码。因此, repobase / mylibrary 的源代码本身不起作用。我必须做setup.py build
。这将创建 repobase / build / lib.linux-x86_64-2.7 / mylibrary 。
有没有合理的方法让py.test使用这个目录导入mylibrary?鉴于这些限制:
我不想在 test_mylibrary.py 中包含任何sys.path
/导入魔法,因为这可能会破坏其他环境中的测试。
我不想放弃从 repobase 运行py.test
的可能性。因此,修改PYTHONPATH无济于事,因为.
仍然是sys.path
中的第一个。因此 repobase / mylibrary 比 repobase / build / lib.linux-x86_64-2.7 / mylibrary 更受青睐。
如果没有,那么需要构建的python库的标准方法是什么?
答案 0 :(得分:6)
我认为你的问题只是py.test没有将构建的共享对象复制到存储库的根目录。
我刚尝试使用py.test在测试C扩展的Python wiki上直接运行UT,如下所示:
python setup.py build
py.test test/examp_unittest.py
AssertionError: No module named examp
失败了。
然而,当我按照wiki跟着这个字母(而不是运行python setup.py test
)时,我注意到它将.so
复制到根目录(注意它开始运行测试之前的最后一行) ):
running test
running egg_info
writing examp.egg-info/PKG-INFO
writing top-level names to examp.egg-info/top_level.txt
writing dependency_links to examp.egg-info/dependency_links.txt
reading manifest file 'examp.egg-info/SOURCES.txt'
writing manifest file 'examp.egg-info/SOURCES.txt'
running build_ext
copying build/lib.linux-x86_64-2.6/examp.so ->
runTest (test.examp_unittest.DeviceTest) ... ok
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
在我的系统上运行它之后,我现在可以在相同的代码库上非常愉快地运行py.test - 如下所示。
============================= test session starts ==============================
platform linux2 -- Python 2.7.3, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
rootdir: /tmp/sotest, inifile:
collected 1 items
test/examp_unittest.py .
=========================== 1 passed in 0.01 seconds ===========================
因此,解决方案是将共享对象复制到存储库的根目录。
为了确保我从头开始运行整个事情,只需构建扩展,复制共享对象然后运行py.test。这一切都按预期工作。
答案 1 :(得分:3)
从聊天讨论中,听起来好像C实现只提供了Python实现功能的一个子集。
一种常见的解决方案是拆分模块,使得需要优化实现的部件存在于单独的模块中。
考虑一个需要在不同图像格式之间转换的库的更具体的例子。
我们假设你的布局看起来像这样......
<body>
<div class="nav">
<div class="links">
<div class="link">
Servers
</div>
</div>
</div>
</body>
...您的repobase
|- image
| |- __init__.py
| |- pyJPEG.py
|- build
| |- lib.linux-x86_64-2.7
| |- cJPEG.so
|- tests
|- test_image.py
包括PYTHONPATH
,/path/to/repobase:/path/to/repobase/build/lib.linux-x86_64-2.7
导出符号cJPEG.so
和jpeg_decompress
,您的文件看起来像这样......
图片/ __初始化__。PY 强>
jpeg_compress
图片/ pyJPEG.py 强>
# Load the C implementation if we have it, otherwise fall back to
# a pure Python implementation
try:
from cJPEG import jpeg_decompress, jpeg_compress
except ImportError:
from pyJPEG import jpeg_decompress, jpeg_compress
def load_image(filename):
data = open(filename, 'rb').read()
if filename.endswidth('.jpg'):
return jpeg_decompress(data)
else:
raise NotImplementedError
def save_image(data, filename, filetype='JPEG'):
if filetype == 'JPEG':
data = jpeg_compress(data)
else:
raise NotImplementedError
open(filename, 'wb').write(data)
通过这种布局,测试套件无需关心是否构建了库 - 您可以在两种情况下使用相同的套件,def jpeg_decompress(data):
# A pure Python implementation of a JPEG decoder
def jpeg_compress(data):
# A pure Python implementation of a JPEG encoder
的存在(或不存在)将决定哪个版本经过测试。