Obtener la ruta LIB de Python

Puedo ver que la ruta INCLUDE es sysconfig.get_path('include') .

Pero no veo ningún valor similar para LIB .

NumPy lo codifica directamente como os.path.join(sys.prefix, "libs") en Windows y get_config_var('LIBDIR') (no documentado y faltante en Windows) de lo contrario.

¿Hay una forma más compatible?

Como no forma parte de ninguna especificación / documento oficial, y, como se muestra en otra respuesta, hay casos en que no se configura ninguna de las variables apropiadas de sysconfig / distutils.sysconfig .get_config_var()

La única forma de obtenerlo de manera confiable en todos los casos, exactamente como lo haría una comstackción (por ejemplo, incluso para un Python en el árbol de origen) es delegar a la implementación de referencia.

En distutils , la lógica que establece la ruta de la biblioteca para un comstackdor se encuentra en distutils.commands.build_ext.finalize_options() . Por lo tanto, este código lo obtendría sin efectos secundarios en la comstackción:

 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 

Tenga en cuenta que:

  • No todas las ubicaciones en la lista resultante necesariamente existen.
  • Si su setup.py se setuptools en setuptools , use setuptools.Distribution y setuptools.command.build_ext en setuptools.command.build_ext lugar, de manera correspondiente.
  • Si pasa valores a setup() que afectan el resultado, también debe pasarlos a Distribution aquí.

Dado que no hay garantías de que el conjunto de valores adicionales que debe pasar permanezca igual o que el siguiente mantenedor no cambie a otro constructor 1 ; y el valor solo es necesario al construir una extensión,

  • Parece que realmente no debes obtener este valor de forma independiente :
    • Si está utilizando otra instalación de comstackción, debería subclasificar build_ext y obtener el valor del método base durante la comstackción.

1 De acuerdo, admito que esta en particular es una posibilidad bastante remota.

A continuación se muestra la subrutina (bastante larga) en skbuild.cmaker que localiza libpythonxx.so / pythonxx.lib para Python en ejecución. En CMake, los Modules/FindPythonLibs.cmake 350 líneas Modules/FindPythonLibs.cmake están dedicados a esta tarea.

Sin embargo, la parte de la primera que obtiene solo el directorio es mucho más simple:

 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