Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

In the user site .pth files are processed once at interpreter startup:

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

And it's the same behaviour in the system site, e.g. /usr/local/lib/python3.8/site-packages/.

But in venv they are processed twice:

$ 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

Why are path configuration files processed twice in a virtual environment?

like image 763
wim Avatar asked Nov 11 '19 19:11

wim


People also ask

Do virtual environments take up space?

virtualenvs , it shows that the size of most of them is over 400MB. The total space consumed by virtualenvs is over 6GB. Also, there are a lot of packages which are common across all the environments and there are few packages which are different.

Where are Virtualenvs stored?

The virtual environment tool creates a folder inside the project directory. By default, the folder is called venv , but you can give it a custom name too. It keeps Python and pip executable files inside the virtual environment folder.

Should I use virtualenv or VENV?

These are almost completely interchangeable, the difference being that virtualenv supports older python versions and has a few more minor unique features, while venv is in the standard library.


1 Answers

Looks like it all happens in the site module (not so surprising). In particular in the site.main() function.

The loading of the .pth files happens either in 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.

In your first example, outside a virtual environment, the file is placed in the directory for user site packages. So the console output happens when site.main() calls site.addusersitepackages().

In the second example, within a virtual environment, the file is placed in the virtual environment's own site packages directory. So the console output happens when 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.

So in short: inside a virtual environment site.addsitepackages() runs twice.

As to what the intention is for this behavior, there is a note:

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

Which, from what I can tell, matters in case the virtual environment has been configured to allow system site packages.

Maybe it could have been solved differently so that the path configuration files are not loaded twice.

like image 74
sinoroc Avatar answered Nov 09 '22 03:11

sinoroc