为什么 .pth 文件在 Python 虚拟环境中加载两次?

Why are .pth files loaded twice in a Python virtual environment?

在用户站点中,解释器启动时处理一次 .pth 文件:

$ echo 'import sys; sys.stdout.write("hello world\n")' > ~/.local/lib/python3.8/site-packages/hello.pth
$ python3.8 -c ""
hello world

这在系统站点中是相同的行为,例如/usr/local/lib/python3.8/site-packages/.

但是在venv中它们被处理了两次:

$ rm ~/.local/lib/python3.8/site-packages/hello.pth
$ /usr/local/bin/python3.8 -m venv .venv
$ source .venv/bin/activate
(.venv) $ echo 'import sys; sys.stdout.write("hello world\n")' > .venv/lib/python3.8/site-packages/hello.pth
(.venv) $ python -c ""
hello world
hello world

为什么路径配置文件在虚拟环境中处理了两次?

看起来这一切都发生在 site 模块中(不足为奇)。特别是在 site.main() 函数中。

.pth 文件的加载发生在 site.addsitepackages() or in site.addusersitepackages(), depending in which folder the file is placed. Well more precisely both these function call site.addpackage(), where it actually happens

在您的第一个示例中,在 虚拟环境 之外,文件放置在用户站点包的目录中。所以控制台输出发生在 site.main() calls site.addusersitepackages().

在第二个示例中,在 虚拟环境 中,文件放置在虚拟环境自己的 站点包 目录中。所以控制台输出发生在 site.main() calls site.addsitepackages() directly and also via site.venv() a couple of lines earlier that also calls site.addsitepackages() if it detects that the interpreter is running inside a virtual environment, i.e. if it finds a pyvenv.cfg file.

简而言之:在虚拟环境中 site.addsitepackages() 运行两次。

至于这种行为的意图是什么,有note

        # Doing this here ensures venv takes precedence over user-site
        addsitepackages(known_paths, [sys.prefix])

据我所知,如果虚拟环境已配置为允许 system site packages

,这很重要

也许可以用不同的方式解决,这样路径配置文件就不会被加载两次。