如何从.so文件导入python模块?

Posted

技术标签:

【中文标题】如何从.so文件导入python模块?【英文标题】:How to import python module from .so file? 【发布时间】:2012-06-10 11:32:20 【问题描述】:
[me@hostname python]$ cat hello_world.cc
#include <string>
#include <Python.h>
#include <boost/python.hpp>

namespace 
  std::string greet()  return "Helloworld"; 


using namespace boost::python;

BOOST_PYTHON_MODULE(hello_world)

  def("greet",greet);


[me@hostnmae python]$ g++ -c -fPIC hello_world.cc -I/path/to/boost/headers -I/path/to/python/headers -o hello_world.o
[me@hostname python]$ g++ -shared -Wl,-soname,libhello_world.so -o libhello_world.so  hello_world.o
[me@hostname python]$ python
Python 2.7.1 (r271:86832, Jan 10 2011, 09:46:57)
[GCC 3.4.5 20051201 (Red Hat 3.4.5-2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path.append('.')
>>> import hello_world
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named hello_world
>>>

我创建了如上所示的 .so 文件,但我无法在 python 中导入。我错过了什么?

【问题讨论】:

【参考方案1】:

获取“hello_world.so”文件并创建名为“hello_world.py”的新python文件(在同一目录中)。 把下面的代码放进去.. .

def __bootstrap__():
   global __bootstrap__, __loader__, __file__
   import sys, pkg_resources, imp
   __file__ = pkg_resources.resource_filename(__name__,'hello_world.so')
   __loader__ = None; del __bootstrap__, __loader__
   imp.load_dynamic(__name__,__file__)
__bootstrap__()

现在您可以将这个 hello_world 导入为:

>>> import hello_world

【讨论】:

是否应该将“_bootstrap_”重命名为“_bootstrap”?我花了很多时间试图找到它的文档,以为它是一个特殊的保留字,但我找不到任何东西。来自python.org/dev/peps/pep-0008/#naming-conventions:_double_leading_and_trailing_underscore_:存在于用户控制的命名空间中的“神奇”对象或属性。例如。 _init_ 、 _import_ 或 _file_ 。永远不要发明这样的名字;仅按文档说明使用。 我们可以复制,但你可以添加一些关于信息的细节。它是如何工作的。 我用模块 readline 试过这个。我碰巧安装了带有 apt-get 的 python 版本 #1 (2.7.12),它有 readline,另一个版本 #2 (2.7.11),只是扩展了,它没有。因此,我在 sys.path 中的一个目录中为版本 #2 添加了 readline.py,并在同一目录中添加了指向 /usr/lib/python2.7/lib-dynload/readline.x86_64-linux-gnu 的符号链接。所以从版本#1开始。我仍然得到错误。 这是唯一的解决方案吗?我没有看到任何 Cython 文档,所以感觉像是一种解决方法。【参考方案2】:

必须叫hello_world.so,而不是libhello_world.so

【讨论】:

谢谢。现在我得到ImportError: ./hello_world.so: undefined symbol: _ZNK12boost_1_47_06python7objects21py_function_impl_base9max_arityEv @balki:你没有链接到 Boost.Python。 我链接了 boost_python,现在我得到了ImportError: libboost_python: cannot open shared object file: No such file or directory。如果我导出LD_LIBRARY_PATH=/path/to/boost_python_lib,它工作正常。如何在 cmdline 中指定? LD_LIBRARY_PATH=/path/to/boost_python_lib python 很简单。如果可以的话,我建议您将boost_python_lib 符号链接到/usr/local/lib,然后您就可以轻松获得它。您还可以通过将-Wl,-rpath=/path/to/boost_python_lib 传递给编译器(实际上由链接器处理)来硬编码.so 文件中的路径。

以上是关于如何从.so文件导入python模块?的主要内容,如果未能解决你的问题,请参考以下文章

python 如何从模块文件夹树导入文件

如何导入安装在站点包中的模块

如何从 Python 中的子文件夹导入模块或文件?

如何在python3中正确导入同一目录下的模块

如何从python中的其他目录导入模块? [复制]

python包与模块导入