编程语言
首页 > 编程语言> > 当从C应用程序中的嵌入式Python调用时,Numpy导入在多数组扩展库上失败

当从C应用程序中的嵌入式Python调用时,Numpy导入在多数组扩展库上失败

作者:互联网

我正在运行一个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时才会出现这种情况,因为当我通过解释器使用它时导入工作.我对答案更感兴趣,这个答案增加了我的理解,而不是快速做到这一点或做了那个修复.我列出了下面的一些系统/问题信息,以及我正在考虑发布关于同一主题的一些其他问题.任何指导表示赞赏!

系统/问题信息:

> Ubuntu 16.04,64位
>使用enabled-shared编译的Python 3.5.5
> numpy导入在解释器中工作(python3.exe和python3.5.exe)
>我确保PySys_SetPath()设置与解释器输出相同的sys.path:import sys,sys.path
>我可以导入其他模块,如PIL和datetimeutil;然而,numpy和pandas是不可导入的(熊猫使用numpy或似乎)
>嵌入式Python使用以下命令:Py_Import_Import(),Py_Initialize()(我确定.它只被调用一次.)等,但它没有获得解释器的全局锁定.
>该应用程序使用CMake构建系统构建,该系统为我的系统编译MakeFiles.
>使用pip3.5 install numpy命令使用pip 9.0.0安装numpy-1.14.2
>导致此错误的python脚本有一行:import numpy …
>我没有我正在导入文件的.zip文件.
>嵌入在C中的Python使用的.exe位于/usr/local/bin / python3(使用Py_GetProgramName()来确定).此.exe链接到libpython3.5m.so.1.0,缺少的符号位于libpython3.5m.so.1.0(运行nm)
> ldd on multiarray.cpython-35m-x86_64-linux-gnu.so显示:

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;但是,要么它们都不符合我的具体情况,要么就像我说的那样存在漏洞.以下是我可能会问的一个子问题列表,如果没有人在这个设置中看到任何明显有关的内容.如果我问他们(在我擦亮之后),我可能会用链接更新问题.

>如何将numpy multiarray.so链接到pythonX.X.so以进行符号解析? ldd似乎没有暗示它曾经做过.在这个link问这个问题
> CMake问题非相关问题在此question解决,于11/12/18询问并于4/16/18回答.
>在.bashrc中设置PYTHONPATH似乎不会更新Py_GetPath()返回的内容,我不得不通过与sys.path不同的方法在site-packages中添加导入.它可能只更新不影响C的bash脚本环境变量.

在这一点上,我不是要求上述问题清单的答案,而是我提供更多线索,知道我的知识差距.

感谢您抽出时间阅读这个问题.任何帮助表示赞赏.

编辑:4/17/18:

好吧,我找到了一个工作,我正在使用它. Dunes问题开始让我更仔细地考虑未定义的符号以及它如何成为链接器/编译器错误,或者numpy导入总是期望具有已经加载到内存中的符号的环境.这让我试图安装不同版本的numpy,看看是否有任何旧版本有所作为.他们没有,但它确实使错误略有不同.当我用Google搜索时,这是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得到回答可以得到一个更好的答案,所以我目前一直坚持提交或接受答案.谢谢!

解决方法:

根本原因

发生此错误的原因是numpy中的multiarray.cpython-35m-x86_64-linux-gnu.so模块依赖于libpythonx.x.so,因为它不是libpythonx.x.so的显式链接.因此,如果您使用ldd -d multiarray.cpython-35m-x86_64-linux-gnu.so,您将无法在列表中看到python.

Python没有问题因为python二进制文件依赖于libpython.x.x.so,所以当numpy使用dlopen加载multiarray.cpython-35m-x86_64-linux-gnu.so时. libdl.so将尝试通过检查主程序的依赖共享库(即python)来解析未定义的符号.它将在libpython.x.x.so中找到它.

在了解了根本原因之后解决方案非常简单,只需帮助libdl.so找到libpython.x.x.so即可.至少有两种方法可以实现这一目标:

>使用dlopen(“libpythonx.x.so”,RTLD_GLOBAL).打开后,使用RTLD_GLOBAL标志,它使libpythonx.x.so中的符号可用于后续加载的共享对象的符号解析.
>在嵌入python的主程序中,将libpythonx.x.so添加到其依赖库中.

标签:python,c,numpy,python-3-x,python-embedding
来源: https://codeday.me/bug/20191004/1854127.html