罐头上写的是什么。
我已经解决了在使用虚拟环境时如何设置sys.prefix
的问题(Python查找pyvenv.cfg
文件[1])。
但是,我不太明白Python是如何找到sys.base_prefix
的。
默认值为/usr/local
(在Unix上)[2]。
但是,这似乎并没有在我的Mac上生效。
如下面的代码所示,后面是符号链接,在本例中,sys.base_prefix
只是实际Python二进制文件上方的目录:
# Following symlinks to determinw where the actual hard link is
➜ tmp ls -l /usr/local/bin/python3
lrwxr-xr-x 1 jeffhemmen admin 38 23 Jul 12:23 /usr/local/bin/python3 -> ../Cellar/python@3.8/3.8.5/bin/python3
➜ tmp ls -l /usr/local/Cellar/python@3.8/3.8.5/bin/python3
lrwxr-xr-x 1 jeffhemmen staff 55 20 Jul 14:26 /usr/local/Cellar/python@3.8/3.8.5/bin/python3 -> ../Frameworks/Python.framework/Versions/3.8/bin/python3
➜ tmp ls -l /usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/bin/python3
lrwxr-xr-x 1 jeffhemmen staff 9 20 Jul 14:26 /usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/bin/python3 -> python3.8
➜ tmp ls -l /usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/bin/python3.8
-rwxr-xr-x 1 jeffhemmen staff 17704 23 Jul 12:23 /usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/bin/python3.8
# Printing sys.base_prefix for all these links
➜ tmp /usr/local/bin/python3 -c "import sys; print(sys.base_prefix)"
/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8
➜ tmp /usr/local/Cellar/python@3.8/3.8.5/bin/python3 -c "import sys; print(sys.base_prefix)"
/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8
➜ tmp /usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/bin/python3 -c "import sys; print(sys.base_prefix)"
/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8
➜ tmp /usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/bin/python3.8 -c "import sys; print(sys.base_prefix)"
/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8
然而,在下面的例子中(同一台计算机,我的Mac),sys.base_prefix
是完全不同的:
➜ tmp ls -l /usr/bin/python3
-rwxr-xr-x 1 root wheel 31488 10 Aug 21:56 /usr/bin/python3
➜ tmp /usr/bin/python3 -c "import sys; print(sys.base_prefix)"
/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.7
我在某个地方读到过,这取决于Python是如何安装的。这是否意味着sys.base_prefix
实际上被编译成了二进制文件?如果没有,是否有一个文本文件(config,.py,...)在Python启动时读取的地方?
**额外问题:**何时/如何/为什么sys.exec_prefix
实际上不同于sys.prefix
(和/或sys.base_exec_prefix
不同于sys.base_prefix`)?
2条答案
按热度按时间42fyovps1#
documentation解释了如何设置值以及虚拟环境如何覆盖它。
这里是sys模块的source code,它似乎是在解释器状态初始化时设置的。我没有继续走下去。
fjnneemd2#
**
Python installation directory
**是一个包含所有目录bin/
、include/
、lib/
、share/
等的目录。任何Python安装都需要。如果你使用的是Ubuntu,它默认的Python安装目录是/usr
。当我们创建一个虚拟环境时,会创建一个Python安装目录,该目录具有环境的名称。任何Python解释器,无论是否有环境,都需要这个目录结构才能正常工作。因此,使用venv
(或任何其他工具,如pyenv
,poetry
或conda
)创建的Python环境将创建具有这些确切名称的目录。例如,如果我们创建一个名为
my_venv
的Python虚拟环境,我们将拥有Python安装目录结构:当我们在shell中输入
python
时,操作系统会遍历PATH
环境变量,查找第一个名为'python'的可执行文件。一旦它找到了一个(它可能是一个符号链接,在这种情况下,它将不会被遵循),Python脚本将使用该解释器开始执行。Python脚本将自动执行的第一件事是询问操作系统它正在使用的解释器的位置,即在PATH
环境变量中找到的解释器。有了这个位置,Python(更准确地说是site.py
模块)将在可执行文件(或符号链接)所在的/bin
目录的上一级查找名为pyenv.py
的文件。如果找到,解释器会理解它是在虚拟环境中;如果没有找到,则解释器将理解它不在虚拟环境中。在虚拟环境中,如果
pyvenv.cfg
文件包含home
键,解释器将使用它来设置sys.base_prefix
和sys_prefix
为:sys.base_prefix
将保存用于创建此虚拟环境的Python installation directory
的路径。为此,解释器将查看pyvenv.cfg
中的home
键。此键将保存用于创建此虚拟环境的Python可执行文件所在目录的路径。如果该可执行文件恰好是一个符号链接,则会跟踪它,直到真实的的可执行文件。托管真实的可执行文件所在的bin/
目录的目录将是用于构建此环境的Python可执行文件的Python安装目录。例如:sys.prefix
将指向包含pyvenv.cfg
文件的目录(如果存在),即虚拟环境的Python安装目录(如果我们正在使用虚拟环境)。如果不使用虚拟环境,则与sys.base_prefix
相同。请注意,这两个“基目录”都具有Python安装的目录结构,即。目录
bin
、include
、lib
等。还要注意,如果我们没有使用虚拟环境,sys.base_prefix
和sys.base
都将被设置为操作系统的Python安装目录。在我的例子中,我使用的是Ubuntu 20.04,所以当不使用虚拟环境时,这些变量是/usr
。同样从Python文档here,
I deduce
中,其他两个变量sys.prefix
和sys.base_prefix
被设置为:sys.base_exec_prefix
:如果在虚拟环境中,它将与sys.base_prefix
相同,即用于创建虚拟环境的Python解释器的Python安装目录。如果不在虚拟环境中,它将是OS Python安装目录。sys.exec_prefix
:如果在虚拟环境中,它将与sys.prefix
相同,即虚拟环境的Python安装目录。如果不在虚拟环境中,它将是OS Python安装目录。换句话说,通过
default
,它们将始终分别与sys.base_prefix
和sys.prefix
相同。阅读了引用的关于
sys.base_prefix
、sys.prefix
、sys.base_exec_prefix
和sys.exec_prefix
的Python文档,我得出的结论是,所有这些变量最初都设置在操作系统的Python安装目录中。之后,如果模块site.py
确定我们处于虚拟环境中,则会继续如上所述更改它们。我还没有发现的是,用不同的名字定义所有这些变量,但它们具有相同的值,背后的原理是什么。
参考书目