将 Python 嵌入到 Linux 程序中

Embedding Python in Linux program

我目前正在尝试将 Python 嵌入到我的 C++ 应用程序中,以便为用户提供高级脚本编写的可能性。 到目前为止,我的程序在 Windows 上运行良好(完全正常运行),现在我正在尝试在 GNU/Linux 上执行相同的操作(目前是 Debian 7),但这给我带来了更多麻烦超出我的预期。 首先,我下载 python.tar.gz 并使用 enable-shared 选项从源代码编译它以获得 fPIC 选项:
./configure --enable-shared --prefix=/opt/python
制作 && 制作 altinstall
然后,我安装了 numpy,感谢 pip:python3.4 -m pip install 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;
}

导入错误:numpy.core.multiarray导入失败
我认为错误很明显,Python 找不到包括 numpy 在内的任何库。但是我已经尝试了从设置 PYTHONPATH 到使用 -Wl,-rpath 设置其他目录的所有方法....甚至 PySys_SetPath... Windows 上的工作在 [=47= 上失败了]. 欢迎任何想法!谢谢。

编辑:这是我使用的 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 可执行文件...

你说 "python can't find any libraries",你试过启动 python 并导入它们吗?如果直接在 python 中导入有问题,您将不得不重新检查 PYTHOPATH 是否正确,或者您安装的文件可能没有安装执行权限设置。 (我遇到过两次)。

此外,您是否从 manual 中查看了在类 unix 系统上编译的技巧?。

It is not necessarily trivial to find the right flags to pass to your compiler (and linker) in order to embed the Python interpreter into your application, particularly because Python needs to load library modules implemented as C dynamic extensions (.so files) linked against it.

To find out the required compiler and linker flags, you can execute the pythonX.Y-config script which is generated as part of the installation process (a python3-config script may also be available)

你如何编译你的代码?

编辑

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

I think the error is pretty clear, Python can't find any libraries including 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 版本安装了 "wrong" numpy。但是根据你的 makefile,你的 python3.4 文件夹中有一个 numpy,如果没有它会抛出错误 No such file or directory。另外你说你甚至不得不使用LD_LIBRARY_PATH推荐顺便说一下)用numpy开始python,这只是意味着numpy确实没有正确指向通过当前为您的 python 定义的任何路径,包括您在编译的 python 中的 site-packages 文件夹(默认搜索)。

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

很抱歉,我无法提供更多帮助,但如果不实际从头开始 python 构建(目前也不在 debian 上),我无法重现该问题。祝你好运,随时关注我?

简短的回答是:不要 link 静态地 Python。 libpython3.4.so 上的所有 Python 模块 link 动态 ,因此 C++ 程序必须执行相同的操作。 总结 Python 嵌入:

  1. Link 在 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()));