使用C扩展构建/测试Python项目

Dim*_*iuc 6 python testing distutils compiled

我有一个带有python包的项目和一个已编译的组件.目前的目录布局是:

<project>
  foo/
  foo/__init__.py
  foo/...

  src/
  src/c_foo.c

  tests/
  tests/test_foo.py

  setup.py
Run Code Online (Sandbox Code Playgroud)

构建项目时,distutils会创建一个build/lib我添加PYTHONPATH或安装到虚拟环境中的目录.结果结构如下:

<project>
  build/lib
  build/lib/foo/__init__.py
  build/lib/foo/c_foo.so
Run Code Online (Sandbox Code Playgroud)

问题在于,如果我从项目根目录启动python解释器会话,从项目根目录等运行测试,它会选择源树而不是构建树.

我找到了几个现有的解决方案:

  1. 将python源放在一个单独的目录下,例如.lib/foo,modules/foo等缺点就是额外的目录级别的所有源文件和不一致与不具有编译的扩展,因此有自己的Python包的根目录下的项目.

  2. 将包保留在根目录中,这意味着不得不chdir离开项目根目录(例如,进入tests /目录),以便python解释器不会看到源包(通过构建脚本或手动).

  3. 使用不同的名称(例如.foo-modulefoo-lib)将包保留在根中,并使用适当的package_dir={'foo':'lib-foo'}setup.py.这是pt的变种.1我没有额外级别的目录层次结构,这几乎是一回事.

  4. 将包保留在根目录中并使用setup.py build_ext --inplace,但这会污染源树.

这两种情况都引入了开销与普通python项目,其中可以从源树中修改/运行代码.我非常希望听到大家对上述优缺点的看法以及您为项目使用的特定方法.

sam*_*ias 1

您可能想尝试分发(以前称为 setuptools)develop中的目标。

确保distribute已安装,然后setup.py像这样修改:

# the setuptools package name is still used
from setuptools import setup, Extension
...
Run Code Online (Sandbox Code Playgroud)

然后输入您的 virtualenv 并运行develop

% source ~/virt/bin/activate
(virt)% cd ~/project
(virt)% python setup.py develop
Run Code Online (Sandbox Code Playgroud)

您应该能够从项目根目录中运行测试,并且无论何时激活该 virtualenv,您都可以访问该项目的包和扩展,无论您的路径如何:

% cd /tmp
% source ~/virt/bin/activate
(virt)% python -c 'import foo, c_foo; print foo, c_foo'

<module 'foo' from '/Users/user/project/foo/__init__.py'>
<module 'c_foo' from '/Users/user/project/c_foo.so'>
Run Code Online (Sandbox Code Playgroud)