【问题标题】:Get Python's LIB path获取 Python 的 LIB 路径
【发布时间】:2017-11-21 21:43:41
【问题描述】:

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

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

NumPy outright hardcodes it 在 Windows 中为 os.path.join(sys.prefix, "libs"),在其他情况下为 get_config_var('LIBDIR')(在 Windows 中未记录和丢失)。

有没有更受支持的方式?

【问题讨论】:

    标签: python python-c-api compiler-options


    【解决方案1】:

    由于它不是任何官方规范/文档的一部分,而且,as shown by another 的答案,在某些情况下没有设置来自 sysconfig/distutils.sysconfig.get_config_var() 的适当变量,

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

    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 并在构建期间从基本方法中获取值。

    【讨论】:

      【解决方案2】:

      下面是(相当长的)subroutine in skbuild.cmaker,它为正在运行的 Python 定位 libpythonxx.so/pythonxx.lib。在 CMake 中,350 行 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
      

      【讨论】:

        猜你喜欢
        • 2021-09-10
        • 1970-01-01
        • 2015-05-14
        • 2019-07-19
        • 2011-12-15
        • 2011-08-30
        • 2014-03-19
        • 2019-07-10
        • 2023-04-05
        相关资源
        最近更新 更多