sys.executable如何确定解释器路径?

How does sys.executable determine the interpreter path?

我用自制程序在 mac 上安装了 python。一些工具(例如 pipenv)有一些麻烦,因为它们试图写入 /lib/python3.7/site-packages/,mac 不允许。经过一番调查后,我发现他们启动了一个新的 python 解释器,该解释器在 sys.executable 中找到,它实际上与自制程序安装的 python 路径不一致。

$ which python
/usr/local/bin/python
$ python -c "import sys; print(sys.executable)"
/usr/local/opt/python/bin/python3.7

我希望这些路径指向同一个二进制文件,为什么不是这样?我怎样才能控制sys.executable

它是在运行时确定的(由 calculate_program_full_path() function in Module/getpath.c 准确地说。它通常基于 OS 传入的 argv[0] 值。

您可以通过设置 PYTHONEXECUTABLE environment variable 来设置替代值。

但是,在自制程序构建中,还有更多的事情要做。 Homebrew 强制问题并直接在 sitecustomize.py module generated at install time:

中设置 sys.executable
$ tail -n2 /usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/sitecustomize.py
    # Set the sys.executable to use the opt_prefix
    sys.executable = '/usr/local/opt/python/bin/python3.7'

这会愉快地忽略 PYTHONEXECUTABLE 即使已设置。

这是怎么回事,为什么自制软件会崩溃 sys.executable

Homebrew Python 是一个 MacOS framework build, so you can run GUI apps with this Python binary. A binary inside a framework bundle is placed under very strict requirements by Apple as to what you can do with it, including what the executable name is allowed to be set to. To work around these the framework binary is actually a wrapper ) 转换到更好的路径,设置 __PYVENV_LAUNCHER__ 环境变量并启动 actual python 二进制文件位于 Resources/Python.app/Contents/MacOS/Python,然后使用 __PYVENV_LAUNCHER__ 环境变量通知 sys.executable

包装器设置的路径已解析目录名称中的任何符号链接。由于 homebrew 使 /usr/local/opt/python 成为特定 Python bottle 目录的符号链接,因此 运行 /usr/local/opt/python/bin/python3 导致 sys.executable 被设置为链接的 bottle 路径:

$ /usr/local/opt/python/bin/python3 -S -c 'import sys; print(sys.executable)'
/usr/local/Cellar/python/3.7.0/bin/python3

这违背了符号链接的目的,并且每次自制程序对 Python 公式进行次要版本更新时都可能导致 pip 安装脚本损坏。

我希望自制程序至少 检查 PYTHONEXECUTABLE 是否已设置 。您可以通过直接设置 sys.executable 来强制自己解决问题:

import os, sys

if 'PYTHONEXECUTABLE' in os.environ and :
    sys.executable = os.environ['PYTHONEXECUTABLE']

我打开了一份报告to request the homebrew Python formula checks for PYTHONEXECUTABLE and included a suggested fix。该修复已于 2018 年 11 月 28 日发布,因此只需更新您的 Python 软件包就可以为您提供新版本,并让 Homebrew Python 再次荣登 PYTHONEXECUTABLE