获取 Python 的 LIB 路径

Get Python's LIB path

我可以看到 INCLUDE 路径是 sysconfig.get_path('include')

但我没有看到 LIB 的任何相似值。

NumPy outright hardcodes it as os.path.join(sys.prefix, "libs") 在 Windows 和 get_config_var('LIBDIR') 中(未记录且在 Windows 中缺失)否则。

有没有更支持的方式?

下面是(相当长的)subroutine in skbuild.cmaker that locates libpythonxx.so/pythonxx.lib for the running Python. In CMake, 350-line Modules/FindPythonLibs.cmake专用于此任务。

前者中仅获取目录的部分要简单得多:

libdir = dustutils.sysconfig.get_config_var('LIBDIR')
if sysconfig.get_config_var('MULTIARCH'):
    masd = sysconfig.get_config_var('multiarchsubdir')
    if masd:
        if masd.startswith(os.sep):
            masd = masd[len(os.sep):]
        libdir = os.path.join(libdir, masd)

if libdir is None:
    libdir = os.path.abspath(os.path.join(
        sysconfig.get_config_var('LIBDEST'), "..", "libs"))

def get_python_library(python_version):
    """Get path to the python library associated with the current python
    interpreter."""
    # determine direct path to libpython
    python_library = sysconfig.get_config_var('LIBRARY')

    # if static (or nonexistent), try to find a suitable dynamic libpython
    if (python_library is None or
            os.path.splitext(python_library)[1][-2:] == '.a'):

        candidate_lib_prefixes = ['', 'lib']

        candidate_extensions = ['.lib', '.so', '.a']
        if sysconfig.get_config_var('WITH_DYLD'):
            candidate_extensions.insert(0, '.dylib')

        candidate_versions = [python_version]
        if python_version:
            candidate_versions.append('')
            candidate_versions.insert(
                0, "".join(python_version.split(".")[:2]))

        abiflags = getattr(sys, 'abiflags', '')
        candidate_abiflags = [abiflags]
        if abiflags:
            candidate_abiflags.append('')

        # Ensure the value injected by virtualenv is
        # returned on windows.
        # Because calling `sysconfig.get_config_var('multiarchsubdir')`
        # returns an empty string on Linux, `du_sysconfig` is only used to
        # get the value of `LIBDIR`.
        libdir = du_sysconfig.get_config_var('LIBDIR')
        if sysconfig.get_config_var('MULTIARCH'):
            masd = sysconfig.get_config_var('multiarchsubdir')
            if masd:
                if masd.startswith(os.sep):
                    masd = masd[len(os.sep):]
                libdir = os.path.join(libdir, masd)

        if libdir is None:
            libdir = os.path.abspath(os.path.join(
                sysconfig.get_config_var('LIBDEST'), "..", "libs"))

        candidates = (
            os.path.join(
                libdir,
                ''.join((pre, 'python', ver, abi, ext))
            )
            for (pre, ext, ver, abi) in itertools.product(
                candidate_lib_prefixes,
                candidate_extensions,
                candidate_versions,
                candidate_abiflags
            )
        )

        for candidate in candidates:
            if os.path.exists(candidate):
                # we found a (likely alternate) libpython
                python_library = candidate
                break

    # TODO(opadron): what happens if we don't find a libpython?

    return python_library

因为它不是任何官方 spec/doc 的一部分,而且 答案,在某些情况下 none 来自 sysconfig/[=12 的适当变量=] .get_config_var() 已设置,

在所有情况下可靠地获得它的唯一方法,完全作为构建(例如,即使对于 Python在sourcetree)是委托给参考实现。

distutils中,为编译器设置库路径的逻辑is located in distutils.commands.build_ext.finalize_options()。因此,这段代码将在构建时没有副作用:

import distutils.command.build_ext    #imports distutils.core, too
d = distutils.core.Distribution()
b = distutils.command.build_ext.build_ext(d)  #or `d.get_command_class('build_ext')(d)',
                                              # then it's enough to import distutils.core
b.finalize_options()
print b.library_dirs

注意:

  • 并非结果列表中的所有位置都一定存在。
  • 如果您的 setup.py 是基于 setuptools 的,请相应地使用 setuptools.Distributionsetuptools.command.build_ext
  • 如果您将影响结果的任何值传递给 setup(),您也必须在此处将它们传递给 Distribution

由于无法保证您需要传递的附加值集会保持不变,并且只有在构建扩展时才需要该值,

  • 似乎你根本不应该独立获得这个值:
    • 如果您正在使用其他构建工具,您应该继承 build_ext 并在构建过程中从基本方法中获取值。