如何从Python中获取Python库的路径

时间:2015-11-04 08:37:54

标签: python swig distutils

初始情况:

我有一个C / C ++库,并为不同的目标语言提供绑定。其中一种语言是Python。我决定使用Swig,因为它为很多语言提供了很好的支持,并且它与CMake的集成非常简单。

为了提高Python绑定及其安装的可用性,我想提供一个setup.py。我们的想法是从setup.py文件中运行CMake,因为CMake包含了如何正确创建绑定的所有逻辑。

我目前得到的内容:

我能够在setup.py中运行CMake并构建Python绑定的目标。

通过设计Swig,CMake文件需要区分Python 2和Python 3.在运行CMake时,它会检测Python安装的位置并配置环境。如果用户同时安装了Python 2和Python 3(及其开发包),CMake总是使用Python 3。

根据:https://cmake.org/cmake/help/v3.0/module/FindPythonLibs.html,可以通过设置PYTHON_LIBRARY和PYTHON_INCLUDE_DIR来指定实际使用的Python版本。例如,我必须运行:

cmake -DPYTHON_INCLUDE_DIR=/usr/include/python2.7 -DPYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython2.7.so

有什么问题:

如果用户执行:

python setup.py build

可执行文件的Python版本' python'可能是2但是CMake使用版本3构建绑定(见上文)。

根据Find python header path from within python?,我可以使用以下方式获取头文件的位置:

from distutils.sysconfig import get_python_inc
get_python_inc()

不幸的是,我不知道如何获取Python库的路径。由Distribution independent libpython path提供的解决方案对我不起作用,因为它总是返回' / usr / lib'而不是' /usr/lib/x86_64-linux-gnu/libpython2.7.so'

问题:

如何从Python中获取Python库的位置(完整路径)。

3 个答案:

答案 0 :(得分:1)

问题:

如何从Python中获取Python库的位置(完整路径)。

答案:

在Python的Makefile中寻找INSTALL_SHARED: https://github.com/python/cpython/blob/3.5/Makefile.pre.in

我们可以找到:

$(INSTALL_SHARED) libpython$(VERSION)$(SO) $(DESTDIR)$(LIBDIR)/$(INSTSONAME); \

我们可以看到所提问息信息中没有单一变量。你需要从另外两个构建它:

from distutils.sysconfig import get_config_var
libpython = "%s/%s" % (get_config_var("LIBDIR"), get_config_var("INSTSONAME"))

在python 2.7中进行测试:

Python 2.7.13 (default, Nov 20 2017, 02:33:01)
[GCC 4.7.2 20121109 (Red Hat 4.7.2-8)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from distutils.sysconfig import get_config_var
>>> "%s/%s" % (get_config_var("LIBDIR"), get_config_var("INSTSONAME"))
'/usr/lib64/libpython2.7.so.1.0'

在python 3.3中测试:

Python 3.3.0 (default, Nov 11 2013, 09:56:47)
[GCC 4.7.2 20121109 (Red Hat 4.7.2-8)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from distutils.sysconfig import get_config_var
>>> "%s/%s" % (get_config_var("LIBDIR"), get_config_var("INSTSONAME"))
'/usr/lib64/libpython3.3m.so.1.0'

所以,它只适用于Linux中的CPython(> = 2.3),你可以在python Makefile中看到,并且无法保证它将在未来工作,无论如何,这在过去的14中没有改变年,自2003年5月11日。

您可以使用Windows的BINDIR和DLLLIBRARY变量,正如您在Makefile中看到的那样:

$(INSTALL_SHARED) libpython$(VERSION)$(SO) $(DESTDIR)$(BINDIR); \

但是,我无法在Windows中进行测试。

答案 1 :(得分:0)

我通过解决方法自行解决了这个问题。也许它可以帮助其他人面对相同或至少类似的问题。

首先,我介绍了环境变量PYTHON_INCLUDE_DIR和PYTHON_LIBRARY,它们与用于配置python路径的CMake的参数名称相同:-DPYTHON_INCLUDE_DIR和-DPYTHON_LIBRARY。此外,我将以下代码添加到我的CMake文件

if(DEFINED ENV{PYTHON_LIBRARY} AND DEFINED ENV{PYTHON_INCLUDE_DIR})
    message(STATUS "Using environment variables PYTHON_LIBRARY and PYTHON_INCLUDE_DIR")
    set(PYTHON_LIBRARY $ENV{PYTHON_LIBRARY})
    set(PYTHON_INCLUDE_DIR $ENV{PYTHON_INCLUDE_DIR})
endif()

它只是将环境变量包装到CMake参数中。现在,用户可以在运行CMake之前定义这些变量而不是参数。

PYTHON_INCLUDE_DIR=/usr/include/python2.7 PYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython2.7.so cmake

由于我的setup.py只是调用CMake而CMake现在能够获取环境变量并将它们分别包装到参数中,因此用户也可以在运行setup.py之前配置变量(或者pip,等)。

PYTHON_INCLUDE_DIR=/usr/include/python2.7 PYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython2.7.so pip install tinyspline

说实话,用户仍然需要配置一些路径,但最终他/她能够这样做。

答案 2 :(得分:0)

我对Python并不了解很多,因此也无法找到一个很好的答案来弄清楚Python库的完整路径和名称。因此,我尝试通过使用以下方法进行测试来提出解决方案:

  • CentOS 7(Python 3.6)
  • Ubuntu 19.10(Python 3.7)
  • Windows 10(来自Chocolatey的Python 3.8)

我使用CMake的find_package(Python3)作为参考,这些是在每个平台上找到的库:

  • CentOS:/usr/lib64/libpython3.6m.so
  • Ubuntu:/usr/lib/python3.7/config-3.7m-x86_64-linux-gnu/libpython3.7m.so
  • Windows:C:/Python38/libs/python38.lib

从那以后,我试图找出是否存在配置变量的任何组合(如distutils.sysconfig.get_config_vars()所报告的那样),这些组合可以为我提供CMake找到的路径和库名。在我看来,不幸的是,没有一种方法可以在所有这些平台上移植以获取完整的库路径。 我能得到的是这些组合似乎可以在每个平台上使用:

  • CentOS:LIBDIR + LDLIBRARY
  • Ubuntu:LIBPL + LDLIBRARY
  • Windows:BINDIR +硬编码libs\python3.lib