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:
setup.py
se setuptools
en setuptools
, use setuptools.Distribution
y setuptools.command.build_ext
en setuptools.command.build_ext
lugar, de manera correspondiente. 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,
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