Skip to main content
 首页 » 编程设计

python-3.x之为什么 python2 和 python3 中的 include 路径不同

2024年11月24日13emanlee

在尝试使我的基于 scons 的构建系统尽可能独立于平台时,我想知道以下问题:

为什么python2返回包含路径/usr/local/include/python2.7?此路径不包含 Python.h,如果我依赖该路径,构建将失败。

python 2

在 python2 中使用 sysconfig:

$ /usr/bin/python2 
Python 2.7.13 (default, Nov 23 2017, 15:37:09)  
[GCC 6.3.0 20170406] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import sysconfig 
>>> sysconfig.get_path('include') 
'/usr/local/include/python2.7' 

给出 /usr/local/include/python2.7。这是一个空文件夹。

从 shell 调用 python2-config:

$ /usr/bin/python2-config --includes 
-I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7 

这给出了不同的路径。我能够在 /usr/include/python2.7 中找到 Python.h

python 3

在 python3 中使用 sysconfig:

$ /usr/bin/python3 
Python 3.5.3 (default, Nov 23 2017, 11:34:05)  
[GCC 6.3.0 20170406] on linux 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import sysconfig 
>>> sysconfig.get_path('include') 
'/usr/include/python3.5m' 

从 shell 调用 python3-config:

/usr/bin/python3-config --includes 
-I/usr/include/python3.5m -I/usr/include/python3.5m 

生成的路径 /usr/include/python3.5m 与 boath 方法相同。 Python.h 位于此处。

python

如果我使用 anaconda python(2 或 3),路径也是一致的(与 python3 一样)。

我已经找到了一些解决方法,例如在 usr/local/include 中放置一个指向 usr/include 的软链接(soft link),或者只是丢弃 local/ 在路径中,但两者看起来都不是一个好的解决方案。

编辑:

目前 python2 中不正确的包含路径使我的构建系统不像我希望的那样独立于平台。如果使用 python2,添加(可选)环境变量 PYTHON_INCLUDE_PATH 可以让我定义正确的路径。但是始终返回正确路径的解决方案会对我有很大帮助(无论是在 python 端还是使用特定于 scons 的功能)。 由于我的构建系统是基于 scons a

请您参考如下方法:

Python uses an installation scheme that differs depending on the platform and on the installation options.

https://docs.python.org/2/library/sysconfig.html#installation-paths

posix_localposix_prefix 等多种方案决定了各种安装目录的位置。似乎 sysconfig 实际上并没有记录用于安装特定 Python 构建的方案——它只有构建信息。

因此,当您调用 sysconfig.get_path() 时,它会根据当前平台的默认值猜测方案 [1]。 Python2.7 sysconfig 猜测posix_local 而Python3 sysconfig 猜测posix_prefix [2].

看起来两个版本的 Python 都是使用 posix_prefix 方案安装的,因此您可以在调用 sysconfig.get_path 时指定:

$ python -c "import sysconfig; print(sysconfig.get_path('include', 'posix_prefix'))" 
/usr/include/python2.7 
 
$ python3 -c "import sysconfig; print(sysconfig.get_path('include', 'posix_prefix'))" 
/usr/include/python3.5m 

[1] https://github.com/python/cpython/blob/2.7/Lib/sysconfig.py#L169

[2] 作为脚本运行sysconfig:

$ python -m sysconfig | head 
Platform: "linux-x86_64" 
Python version: "2.7" 
Current installation scheme: "posix_local" 
 
$ python3 -m sysconfig | head 
Platform: "linux-x86_64" 
Python version: "3.5" 
Current installation scheme: "posix_prefix" 

我实际上在 sysconfig 源中找不到 posix_local,所以不确定它来自哪里。

编辑

我对此进行了更多研究,了解到它特定于 Debian/Ubuntu 版本的 Python;上游 Python 不使用 /usr/local/ 或具有 posix_local 方案。 Debian 软件包使用一种混合方法,它与 posix_prefix 相同,只是为模块添加了 /usr/local/

我没有在网上找到源链接,但我的本地系统在其 Python2.7 sysconfig.py 中有这个(注意 FIXME):

def _get_default_scheme(): 
    if os.name == 'posix': 
        # the default scheme for posix on Debian/Ubuntu is posix_local 
        # FIXME: return dist-packages/posix_prefix only for 
        #   is_default_prefix and 'PYTHONUSERBASE' not in os.environ and 'real_prefix' not in sys.__dict__ 
        # is_default_prefix = not prefix or os.path.normpath(prefix) in ('/usr', '/usr/local') 
        return 'posix_local' 
    return os.name 

Debian python3 sysconfig.py 取消了 posix_local 并使用与上游 python 相同的默认值:

def _get_default_scheme(): 
    if os.name == 'posix': 
        # the default scheme for posix is posix_prefix 
        return 'posix_prefix' 
    return os.name 

您可能希望复制它以与 Mac 或 Windows 兼容:

sysconfig.get_path('include', 'posix_prefix' if os.name == 'posix' else os.name) 

https://wiki.debian.org/Python#Deviations_from_upstream
https://www.debian.org/doc/packaging-manuals/python-policy/python.html#paths