将boost python扩展放在包内

时间:2014-01-01 20:05:37

标签: c++ python-2.7 boost-python

我有以下boost python代码:

#include <boost/python.hpp>

namespace bp = boost::python;

class PyExtTest
{
public:
    std::string get_name() { return m_name; }
    void set_name(std::string const& name) { m_name = name; }

private:
    std::string m_name;
};

BOOST_PYTHON_MODULE(test_ext)
{
    bp::class_<PyExtTest>("pet")
        .add_property("name", &PyExtTest::get_name, &PyExtTest::set_name)
        ;
}

我使用distutils编译到以下目录层次结构中:

build/lib/test_ext.so

然后使用(将PYTHONPATH设置为build/lib),如下所示:

import test_ext
a = test_ext.pet
a.name = 'dog'
print a.name     # dog

当我配置distutils以安装test_ext作为包pkg的一部分时,python无法再找到该模块。我最终得到了目录层次结构:

build/lib/pkg
build/lib/pkg/__init__.py
build/lib/pkg/test_ext.so

使用如下设置脚本:

test_module = Extension('pkg.test_ext'
                        , define_macros = module_macros
                        , extra_compile_args = module_compiler_flags
                        , sources = ['pkg/test_ext/test.cpp']
                        , include_dirs = module_include_dirs
                        , library_dirs = module_lib_dirs
                        , libraries = module_libs)

setup (name = 'Test'
       , version = '0.1'
       , description = 'Test'
       , packages = ['pkg']
       , ext_modules = [test_module])

但尝试导入模块:

import pkg.test_ext

导致错误:

ImportError: No module named test_ext

如果我将纯python模块替换为test_ext,那么一切都按预期工作。

我认为我需要以某种方式更改提升代码以指示test_ext扩展名在pkg包内,但我无法确切知道如何执行此操作。

我尝试将test_ext.so移动到build/lib目录层次结构中的正确位置以获取我想要的包布局,但唯一将其识别为模块的位置直接位于{{1 }}。这与build/lib文件不同,我可以从我将它们放在目录层次结构中的任何地方成功导入。

我正在使用.pypython 2.7.6

感谢任何帮助。

1 个答案:

答案 0 :(得分:4)

如Boost.Python Creating Packages教程所示,导入纯python模块和python扩展模块之间没有什么特别的要求。


给定以下目录结构,其中src/pkg/__init__.py为空,src/test_ext/test_ext.cpp包含问题中发布的Boost.Python代码:

.
|-- setup.py
'-- src
    |-- pkg
    |   '-- __init__.py
    '-- test_ext
        └'-- test_ext.cpp

使用以下setup.py文件包含特定于我的环境的路径:

from distutils.core import setup, Extension

test_module = Extension('pkg.test_ext',
                        sources=['src/test_ext/test_ext.cpp'],
                        include_dirs=['/usr/local/include'],
                        library_dirs=['/usr/local/lib/boost'],
                        runtime_library_dirs=['/usr/local/lib/boost'],
                        libraries=['boost_python'])

setup(name='Test',
      version='0.1',
      description='Test',
      package_dir={'': 'src'},
      packages=['pkg'],
      ext_modules=[test_module])

python setup.py build命令生成以下目录树:

.
|-- build
¦   |-- lib.linux-i686-2.7
¦   ¦   '-- pkg
¦   ¦       |-- __init__.py
¦   ¦       '-- test_ext.so
¦   '-- temp.linux-i686-2.7
¦       '-- src
¦           '-- test_ext
¦               '-- test_ext.o
|-- setup.py
'-- src
    |-- pkg
    ¦   '-- __init__.py
    '-- test_ext
        '-- test_ext.cpp

可以通过将pkg.text_ext目录路径添加到Python Module Search Path来导入build/lib.linux-i686-2.7模块。例如,要么将路径附加到:

  • 启动解释器之前的PYTHONPATH环境变量
  • 解释器中的sys.path列表。

在此示例中,我选择从包含build的目录启动解释器,并将build/lib.linux-i686-2.7追加到sys.path

>>> import sys
>>> sys.path.append('build/lib.linux-i686-2.7')
>>> import pkg.test_ext
>>> parrot = pkg.test_ext.pet()
>>> parrot
<pkg.test_ext.pet object at 0xb7439a7c>
>>> parrot.name = 'Polly'
>>> print parrot.name
Polly

如果导入模块时仍然出现故障,请考虑使用-vv参数运行python。这将导致python为导入时检查的每个文件打印详细跟踪消息。查看Python搜索和查找pkg包的位置可能会有所帮助,但无法找到test_ext模块。例如,如果我从src目录中启动Python解释器:

src$ python -vv
# ... some python loading verbose tracing ...
>>> import
# ... get the verbose tracing for the imports import needs out of the way...
  File "<stdin>", line 1
    import
         ^
SyntaxError: invalid syntax
>>> import pkg.test_ext
import pkg # directory pkg
# trying pkg/__init__.i386-linux-gnu.so
# trying pkg/__init__.so
# trying pkg/__init__module.so
# trying pkg/__init__.py
import pkg # from pkg/__init__.py
# wrote pkg/__init__.pyc
# trying pkg/test_ext.i386-linux-gnu.so
# trying pkg/test_ext.so
# trying pkg/test_extmodule.so
# trying pkg/test_ext.py
# trying pkg/test_ext.pyc
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named test_ext

可以看到找到pkg包相对于我当前的工作目录,但是在尝试各种扩展后它没有找到test_ext模块。