我有以下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
文件不同,我可以从我将它们放在目录层次结构中的任何地方成功导入。
我正在使用.py
和python 2.7.6
。
感谢任何帮助。
答案 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
模块。