将boost python扩展名放入包中

Ran*_*its 3 c++ boost-python python-2.7

我有以下增强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)
        ;
}
Run Code Online (Sandbox Code Playgroud)

我使用distutils将其编译为以下目录层次结构:

build/lib/test_ext.so
Run Code Online (Sandbox Code Playgroud)

然后按以下方式使用(PYTHONPATH设置为build/lib):

import test_ext
a = test_ext.pet
a.name = 'dog'
print a.name     # dog
Run Code Online (Sandbox Code Playgroud)

当我将distutils配置为test_ext作为package的一部分安装时pkg,python不再能够找到该模块。我最终得到目录层次结构:

build/lib/pkg
build/lib/pkg/__init__.py
build/lib/pkg/test_ext.so
Run Code Online (Sandbox Code Playgroud)

使用以下安装脚本:

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])
Run Code Online (Sandbox Code Playgroud)

但尝试导入模块:

import pkg.test_ext
Run Code Online (Sandbox Code Playgroud)

导致错误:

ImportError: No module named test_ext
Run Code Online (Sandbox Code Playgroud)

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

我想我需要以某种方式更改boost代码,以指示test_ext扩展名在pkg软件包中,但是我无法确切地知道如何做到这一点。

我尝试仅移动test_ext.sobuild/lib目录层次结构中的正确位置以获取所需的程序包布局,但是将其识别为模块的唯一位置是在的正下方build/lib。这与.py文件不同,无论将它们放在目录层次结构中的任何位置,都可以成功导入这些文件。

我正在使用python 2.7.6boost 1.55

任何帮助表示赞赏。

Tan*_*ury 6

如Boost.Python Creating Packages教程中所示,在导入纯python模块和python扩展模块之间并不需要任何特殊要求。


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

.
|-- setup.py
'-- src
    |-- pkg
    |   '-- __init__.py
    '-- test_ext
        ?'-- test_ext.cpp
Run Code Online (Sandbox Code Playgroud)

通过以下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])
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

pkg.text_ext模块可通过将被导入build/lib.linux-i686-2.7到Python的目录路径模块搜索路径。例如,将路径附加到:

  • 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
Run Code Online (Sandbox Code Playgroud)

如果导入模块时仍然发生故障,请考虑使用带-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
Run Code Online (Sandbox Code Playgroud)

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