在尝试使我的基于 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_local
和posix_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