如何从 Python 内部获取 Python 库的路径

Mar*_*cel 5 python swig distutils

初始情况:

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

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

我目前得到的:

我能够运行 CMake 并从 setup.py 中构建 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
Run Code Online (Sandbox Code Playgroud)

问题是什么:

如果用户执行:

python setup.py build
Run Code Online (Sandbox Code Playgroud)

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

根据从 python 中查找 python 头路径?我可以使用以下方法获取头文件的位置:

from distutils.sysconfig import get_python_inc
get_python_inc()
Run Code Online (Sandbox Code Playgroud)

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

问题:

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

TMa*_*nte 5

我不太了解 Python,而且我没有找到解决 Python 库的完整路径和名称问题的好答案。所以我尝试通过使用以下方法进行测试来提出解决方案:

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

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

  • CentOS:/usr/lib64/libpython3.6m.so
  • 乌班图:/usr/lib/python3.7/config-3.7m-x86_64-linux-gnu/libpython3.7m.so
  • 视窗:C:/Python38/libs/python38.lib

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

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


Mar*_*cel 0

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

首先,我引入了环境变量 PYTHON_INCLUDE_DIR 和 PYTHON_LIBRARY,它们与 CMake 中用于配置 python 路径的参数同名:-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()
Run Code Online (Sandbox Code Playgroud)

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

PYTHON_INCLUDE_DIR=/usr/include/python2.7 PYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython2.7.so cmake
Run Code Online (Sandbox Code Playgroud)

由于我的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
Run Code Online (Sandbox Code Playgroud)

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