在Linux程序中嵌入Python

时间:2015-03-05 11:06:54

标签: python c++ linux python-3.4 python-c-api

我目前正在尝试在我的C ++应用程序中嵌入Python,以便为用户提供高级脚本编写的可能性。 到目前为止,我的程序在Windows上工作得很好(它完全正常工作),现在我正在尝试在GNU / Linux(现在的Debian 7)上做同样的事情,但这给我带来的麻烦比我预期的要多得多。 首先,我下载python.tar.gz并使用enable-shared选项从源代码编译它以获取fPIC选项:
./configure --enable-shared --prefix = / opt / python
制造&&使altinstall
然后,由于pip:python3.4 -m pip install numpy,我安装了numpy。简单。

最后,我安装复制到另一个位置(是的,它应该部署在任何地方),准确地在我的主目录中,并将其命名为python_install。这个副本似乎给了我很多痛苦。

在代码方面,我调用了Py_Initialize,它运行良好。以下是我到目前为止所做的事情:

#include "Python.h"

#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include "numpy/arrayobject.h"

#include <iostream>

int InitNumpy()
{
    import_array();
}

int main()
{
    std::string python_home = "/home/xxxx/dev/test-python/python_install";
    setenv("PYTHONHOME", python_home.c_str(),1 );

    Py_Initialize();

    std::cout << "Importing Numpy... ";
    int cr = InitNumpy();
    std::cout << cr << std::endl;

    return 0;
}

ImportError:numpy.core.multiarray无法导入
我认为错误很明显,Python找不到包括numpy在内的任何库。但是我已经尝试了从设置PYTHONPATH到使用-Wl,-rpath来设置其他目录....甚至PySys_SetPath ......在Windows上运行的是在Linux上失败的。 任何想法都会受到欢迎!感谢。

编辑:这是我使用的(已更正)的makefile:

CC=g++
CFLAGS= -Ipython_install/include/python3.4m -Ipython_install/lib/python3.4/site-packages/numpy/core/include -Wno-unused-result  -DNDEBUG -g -fwrapv -O3 -Wall
#Wrong
#LDFLAGS= -Lpython_install/lib/python3.4/config-3.4m -lpython3.4m -lpthread -ldl  -lutil -lm  -Xlinker -export-dynamic -Wl,-rpath,\$${ORIGIN}/python_install/lib
#Right
LDFLAGS= -Lpython_install/lib/ -lpython3.4m -lpthread -ldl  -lutil -lm  -Xlinker -export-dynamic -Wl,-rpath,\$${ORIGIN}/python_install/lib
EXEC=test-python

all: $(EXEC)

test-python: test-python.o
    $(CC) -o $@ $^ $(LDFLAGS)

%.o: %.cpp
    $(CC) -o $@ -c $< $(CFLAGS)

.PHONY: clean mrproper

clean:
    rm -rf *.o

mrproper: clean
    rm -rf $(EXEC)

选项直接来自python3.4m-config可执行文件...

2 个答案:

答案 0 :(得分:3)

简短的回答是:不要在Python上静态链接。所有Python模块都在libpython3.4.so上链接动态,因此C ++程序必须这样做。 总结Python嵌入:

  1. 在Python上动态链接(参见纠正的Makefile)。使用rpath找到python .so。
  2. 在C ++代码中,将PYTHONHOME环境变量设置为Python安装或使用Py_SetPythonHome()函数。
  3. 致电Py_Initialize();
  4. 如果要导入自定义模块,请将模块路径添加到Python路径。

    PyObject *sys = PyImport_ImportModule("sys");
    PyObject *path = PyObject_GetAttrString(sys, "path");
    PyList_Append(path, PyUnicode_FromString(sys_path.toUtf8().data()));
    

答案 1 :(得分:1)

你说“python找不到任何库”,你试过启动python并导入它们吗?如果直接在python中导入是一个问题,那么您将不得不重新检查PYTHOPATH是否正确,或者您安装的文件是否未安装以及要执行的权限设置。 (我已经两次了)。

另外,您是否已从manual?查看了在unix类系统上编译的提示?

  

找到传递给你的正确旗帜并不一定是微不足道的   编译器(和链接器)以嵌入Python解释器   你的应用程序,特别是因为Python需要加载库   模块实现为链接的C动态扩展(.so文件)   它

     

要找出所需的编译器和链接器标志,您可以执行   pythonX.Y-config脚本,作为一部分生成   安装过程(也可以使用python3-config脚本)

如何编译代码?

修改

我已尽力重现您的错误,但无法在我的机器上执行此操作。我得到的最远的是我认为你对错误的分析是错误的。

  

我认为错误很明显,Python找不到任何库   包括numpy。

拥有import_array()背后的原因是检查是否存在numpy以及你所拥有的numpy版本是否与已安装的python版本相匹配。在源中,它被定义为宏(即对于py2的np):

#if PY_VERSION_HEX >= 0x03000000
#define NUMPY_IMPORT_ARRAY_RETVAL NULL
#else
#define NUMPY_IMPORT_ARRAY_RETVAL
#endif

#define import_array() {if (_import_array() < 0) {PyErr_Print();
PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to
import"); return NUMPY_IMPORT_ARRAY_RETVAL; } }

由于这是你看到的错误,我有理由怀疑你的pip为你的python版本安装了“错误”的numpy。但是再次基于你的makefile,你的python3.4文件夹中有一个numpy,如果它没有它会抛出错误No such file or directory。另外你说你甚至不得不使用LD_LIBRARY_PATH推荐的btw)用numpy启动python,这只意味着当前定义的任何路径都没有正确指出numpy对于你的python,包括你编译的python中的site-packages文件夹(默认搜索)。

我怀疑您默认安装了预先存在的python,并且系统范围的环境路径已设置为它。但考虑到你明确链接python3文件夹中的numpy AND setenv PYTHONHOME,这是一个非常奇怪的陈述。

对不起,我无法提供更多的帮助,但如果没有从头开始实际进行python构建(目前还没有在debian上),我无法重现这个问题。祝你好运,让我发布?