我正在运行一个 C++ 应用程序,它尝试使用 https://docs.python.org/3.5/extending/embedding.html 运行 python函数调用。这是应用程序错误消息管道给我的错误。
class 'ImportError': Importing the multiarray numpy extension module failed. Most likely you are trying to import a failed build of numpy. If you're working with a numpy git repo, try
git clean -xdf
(removes all files not under version control). Otherwise reinstall numpy.Original error was: /usr/local/lib/python3.5/site-packages/numpy/core/multiarray.cpython-35m-x86_64-linux-gnu.so: undefined symbol: PyExc_UserWarning
我很困惑,因为只有在 C++ 中嵌入 Python 时才会发生这种情况,因为当我通过解释器使用它时,导入工作。我对增加我理解的答案更感兴趣,而不是快速做这个或做那个修复。我在下面列出了一些系统/问题信息,以及我正在考虑发布的关于同一主题的一些其他问题。任何指导表示赞赏!
系统/问题信息:
import sys
, sys.path
Py_Import_Import()
, Py_Initialize()
(我确定。它只被调用一次。)等等,但它没有在解释器上获得全局锁定。 pip3.5 install numpy
使用 pip 9.0.0 安装 numpy-1.14.2命令 import numpy
... ldd multiarray.cpython-35m-x86_64-linux-gnu.so
linux-vdso.so.1 => (0x00007ffd9e36b000)
libopenblasp-r0-39a31c03.2.18.so => /usr/local/lib/python3.5/site-packages/numpy/core/./../.libs/libopenblasp-r0-39a31c03.2.18.so (0x00007fdbe149b000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fdbe1192000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fdbe0f75000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fdbe0bab000) /lib64/ld-linux-x86-64.so.2 (0x00007fdbe3ed5000)
libgfortran-ed201abd.so.3.0.0 => /usr/local/lib/python3.5/site-packages/numpy/core/./../.libs/libgfortran-ed201abd.so.3.0.0 (0x00007fdbe08b1000)
我可以/可能会尝试通过不同的方式重新安装 numpy,但我无法跟踪为什么这可能会起作用。
在这一点上,我假设我的知识存在一些漏洞。我查看了很多关于在 C++ 中嵌入 Python 时无法导入多数组组件和 numpy 的类似帖子;但是,要么它们都不符合我的具体情况,要么正如我所说的那样存在漏洞。以下是我可能会问的子问题列表,是否没有人在此设置中看到任何明显相关的内容。当/如果我问他们(在我润色之后),我可能会用链接更新问题。
在这一点上,我不是在寻求上述问题列表的答案,而是提供更多关于我的知识差距可能在哪里的线索。
感谢您抽出宝贵的时间阅读这个问题。任何帮助表示赞赏。
编辑:4/17/18:
嗯,我找到了一个解决方法,我目前正在使用它。沙丘问题开始让我更仔细地思考 undefined symbol ,以及它如何可能是链接器/编译器错误,或者 numpy 导入总是期望一个环境,这些符号已经加载到内存中。这让我尝试安装不同版本的 numpy 以查看是否有任何旧版本有所不同。他们没有,但它确实使抛出的错误略有不同。当我用谷歌搜索时,这个 question appeared .接受的答案通过将这两行添加到 pythonInterface.cpp 给了我一个解决方法:
#include <dlfcn.h>
dlopen("libpython3.5m.so.1.0", RTLD_LAZY | RTLD_GLOBAL)
这些命令添加了要加载的共享库并可用于 cpython.multiarray.so。
这不是指向特定 .so 的理想解决方案,这可能因机器而异。它暂时解决了这个问题,但它也可能导致错误,如果 pythonInterface.so 的链接库发生更改,并且此行未更新,则在 python 调用过程中可能会发生共享库不匹配的错误。我相信如果这个 sub-question 可以得到更好的答案已回答,所以我目前正在等待提交或接受答案,直到那时。谢谢!
最佳答案
根本原因
发生此错误的原因是 multiarray.cpython-35m-x86_64-linux-gnu.so
numpy 中的模块取决于 libpythonx.x.so
,如果不是显式链接libpythonx.x.so
.所以如果你使用 ldd -d multiarray.cpython-35m-x86_64-linux-gnu.so
您不会在列表中看到 python。
Python 没有问题,因为 Python 二进制文件依赖于 libpython.x.x.so
,所以当 numpy 加载 multiarray.cpython-35m-x86_64-linux-gnu.so
通过使用 dlopen
. libdl.so
将尝试通过检查 python 主程序的依赖共享库来解析 undefined symbol 。它将在 libpython.x.x.so
中找到它.
解决方案
知道根本原因后解决方法很简单,只需要帮助libdl.so
能够找到libpython.x.x.so
.至少有两种方法可以实现:
dlopen("libpythonx.x.so", RTLD_GLOBAL)
.打开后使用 RTLD_GLOBAL
标志,它使 libpythonx.x.so 中的符号可用于随后加载的共享对象的符号解析。 libpythonx.x.so
进入它的依赖库。 关于python - 从 C++ 应用程序中的嵌入式 Python 调用时,多数组扩展库上的 Numpy 导入失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49784583/