[英]How do Python Virtual Environment Symlinks Work?
If I create a Python virtual environment like so:如果我像这样创建一个 Python 虚拟环境:
$ python3 -m venv my_venv
... and then look at the Python binary in the bin directory like so: ...然后查看 bin 目录中的 Python 二进制文件,如下所示:
$ ls -l my_env/bin/python*
lrwxrwxrwx 1 fred fred 7 Sep 12 15:57 my_env/bin/python -> python3
lrwxrwxrwx 1 fred fred 16 Sep 12 15:57 my_env/bin/python3 -> /usr/bin/python3
I see that the python
is symlinked to the main global python
.我看到
python
链接到主要的全局python
。 Therefore, what mechanism ensures that the Python packages we install after activating the virtual environment, that the packages are installed to site-packages
?因此,什么机制可以确保我们在激活虚拟环境后安装的 Python 包安装到
site-packages
?
I was interested so I did a little searching and performed a couple experiments.我很感兴趣,所以我做了一些搜索并进行了一些实验。 A reference: How do I find the location of my Python site-packages directory?
参考: 如何找到我的 Python 站点包目录的位置?
I created a virtual environment my_venv in /tmp and did not activate it.我在 /tmp 中创建了一个虚拟环境 my_venv 并没有激活它。 On Linux activating a virtual environment (
my_venv/bin/activate
) adds the virtual environment's bin
directory to the path;在 Linux 上激活虚拟环境(
my_venv/bin/activate
)将虚拟环境的bin
目录添加到路径中; I found I could simulate that by using the full path;我发现我可以通过使用完整路径来模拟它; ie, executing
./my_venv/bin/python
and ./my_venv/bin/pip
directly.即,直接执行
./my_venv/bin/python
和./my_venv/bin/pip
。 Results of such experimentation:此类实验的结果:
> ################### system executables
> python3 -m site # system's python
sys.path = [
<current directory>
'/usr/lib/python310.zip',
'/usr/lib/python3.10',
'/usr/lib/python3.10/lib-dynload',
'/usr/local/lib/python3.10/dist-packages',
'/usr/lib/python3/dist-packages',
]
> pip3 show <a package> # system's pip
...
Location: /usr/lib/python3/dist-packages
...
> pip3 show <package installed in the venv>
WARNING: Package(s) not found
> ################### venv executables
> /tmp/my_venv/bin/python3 -m site
sys.path = [
<current directory>
'/usr/lib/python310.zip',
'/usr/lib/python3.10',
'/usr/lib/python3.10/lib-dynload',
'/tmp/my_venv/lib/python3.10/site-packages
]
> /tmp/my_venv/bin/pip3 show <package installed in the venv>
...
Location: /tmp/my_venv/lib/python3.10/site-packages
...
> /tmp/my_venv/bin/pip3 show <package installed on the system>
WARNING: Package(s) not found
I took a peek at the activation script, /tmp/my_venv/bin/activate
.我看了看激活脚本
/tmp/my_venv/bin/activate
。 It set a couple environment variables, notably one named VIRTUAL_ENV
.它设置了几个环境变量,特别是一个名为
VIRTUAL_ENV
的环境变量。 I set this environment variable to the path to my virtual environment, as it would have been set if I'd activated the virtual environment.我将此环境变量设置为我的虚拟环境的路径,因为如果我激活了虚拟环境,它就会被设置。 Then I checked paths using the system's
python -m site
and pip show <package>
, and got the same responses I'd gotten without the environment variable set.然后我使用系统的
python -m site
和pip show <package>
检查了路径,并得到了与没有设置环境变量时相同的响应。 From this information I concluded that python and pip probably don't pay attention to the environment variable.从这些信息中我得出结论,python 和 pip 可能不注意环境变量。
I then symlinked the system's python3
and pip3
executables to a local directory, and got the same responses from commands using these ( ./python3
and ./pip3
) that I'd gotten from the system executables.然后,我将系统的
python3
和pip3
可执行文件符号链接到本地目录,并从使用这些( ./python3
和./pip3
)的命令中获得了与我从系统可执行文件中获得的相同响应。
I then created the following directory structure:然后我创建了以下目录结构:
bin/python3 # symlink to system python3
bin/pip3 # symlink to system pip3
lib/python3.10/site-packages/
These still gave me the system paths.这些仍然给了我系统路径。 However, as soon as I copied the file
pyvenv.cfg
from a virtual environment into my directory structure, it started to use my local paths!但是,一旦我将文件
pyvenv.cfg
从虚拟环境复制到我的目录结构中,它就开始使用我的本地路径!
Note: I copied pyvenv.cfg straight from the real virtual environment without changing it.注意:我直接从真实的虚拟环境中复制了 pyvenv.cfg,没有对其进行更改。 That file contained the line "home = /usr/bin/".
该文件包含行“home = /usr/bin/”。
I concluded that in order to determine the path to site-packages, Python uses the path of the executed file by preference (even if that's a symlink), and knows to look for a virtual environment configuration file one directory up from the executable.我得出的结论是,为了确定站点包的路径,Python 会优先使用执行文件的路径(即使那是符号链接),并且知道从可执行文件的上一个目录查找虚拟环境配置文件。 If the path is a symlink and doesn't yield a valid path, looks like it is able to back to the path of the actual executed file.
如果路径是符号链接并且没有产生有效路径,则看起来它能够返回到实际执行文件的路径。
(this agrees with sinoroc 's summary of PEP 405 – Python Virtual Environments , written while I was fooling around) (这与sinoroc对PEP 405 – Python Virtual Environments的总结一致,是我胡闹的时候写的)
This is deductive, of course.这当然是演绎的。 The source code would also provide the definitive answer.
源代码也将提供明确的答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.