简体   繁体   English

Python 虚拟环境符号链接如何工作?

[英]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 sitepip 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.然后,我将系统的python3pip3可执行文件符号链接到本地目录,并从使用这些( ./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) (这与sinorocPEP 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM