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

6

我已经使用homebrew在Mac上安装了Python。一些工具(例如pipenv)会遇到一些问题,因为它们尝试写入/lib/python3.7/site-packages/,但这在Mac下不被允许。经过一番调查,我发现它们启动了一个新的Python解释器,该解释器位于sys.executable中,实际上与homebrew安装的Python路径不一致。

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

我认为这些路径应该指向同一个二进制文件,为什么不是呢?我该如何控制sys.executable


/usr/local/bin/python 是一个符号链接吗?你不应该使用 sys.argv[0] 吗?https://docs.python.org/3/library/sys.html#sys.argv - Geza Lore
1个回答

10

精确来说,它是在运行时(由 Module/getpath.c 中的 calculate_program_full_path() 函数确定的)。通常基于操作系统传递的 argv[0] 值。

您可以通过设置 PYTHONEXECUTABLE 环境变量 来设置替代值。

然而,在 Homebrew 构建中,还有一些其他的事情正在进行。Homebrew 强制执行并直接在 sitecustomize.py 模块 中设置了 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

那么到底发生了什么?为什么Homebrew会破坏sys.executable?

Homebrew Python是一个macOS框架构建,因此您可以使用此Python二进制文件运行GUI应用程序。框架包中的二进制文件受到苹果公司非常严格的要求,包括允许设置可执行文件名称的内容。为了解决这些问题,框架二进制文件实际上是一个包装器,它会将其转换为更好的路径、设置__PYVENV_LAUNCHER__环境变量并启动位于Resources/Python.app/Contents/MacOS/Python实际 python二进制文件,然后使用__PYVENV_LAUNCHER__环境变量来通知sys.executable

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

$ /usr/local/opt/python/bin/python3 -S -c 'import sys; print(sys.executable)'
/usr/local/Cellar/python/3.7.0/bin/python3
这会使符号链接失去意义并可能导致pip安装的脚本在homebrew对Python配方进行小版本更新时出现错误。
我希望homebrew至少在此处检查是否设置了“PYTHONEXECUTABLE”。您可以通过直接设置“sys.executable”来强制执行此操作。
import os, sys

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

我已经发起了一个报告,申请Homebrew Python配方检查PYTHONEXECUTABLE,并包含了建议的修复措施。这个修复措施于2018年11月28日已经投入使用,所以只需要更新您的Python包就可以获得新版本,并让Homebrew Python再次支持PYTHONEXECUTABLE


感谢您提供详细的答案,我从未想过这是如此复杂的。同时,我发现pipenv尝试写入/lib/...的事实是由于项目文件夹中留下了一个来自先前版本的setup.cfg;删除它可以使一切正常工作。但无论如何,这是一个非常有趣的话题,我学到了新东西。 - MrTJ
@MrTJ:没错,如果你一开始提到你有Pipenv的问题,我就能更专注于解决这个新的问题了 :) - Martijn Pieters
@MrTJ:据我所知,setup.cfg不会对pipenv产生如此大的影响;您是否使用了pipenv install -e .以包括当前设置好setuptools的项目? - Martijn Pieters
1
Homebrew现在支持PYTHONEXECUTABLE - Stefan Dragnev
1
@StefanDragnev:谢谢提醒,我本来就想更新一下,我的拉取请求已被接受并合并了。 - Martijn Pieters
现在我们应该说服 venv 模块的维护者在虚拟环境激活时设置 PYTHONEXECUTABLE。 - karolyi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接