精确来说,它是在运行时(由 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
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
。
/usr/local/bin/python
是一个符号链接吗?你不应该使用sys.argv[0]
吗?https://docs.python.org/3/library/sys.html#sys.argv - Geza Lore