Pathlib resolves a virtualenv's python to the global python?

Hi All,

First time posting.

I’m working on a personal CLI automation project that uses virtualenv to create python virtual environments in directories for me (among loads of other things there’s no point describing here).

Anyway, I ran into a very tricky to solve bug(?) which turned out to be to do with how pathlib resolves a virtual environment’s python.

I’ve attached a succinct example using the REPL where I create a pathlib.Path object representing the currently active virtual environment’s python executable. All appears well and as expected.

But when I call .resolve() on that path, it returns a Path of my global system python (I don’t actually use my system python, I have pyenv instead).

I’ve tried googling and looking through bug trackers etc and can’t seem to find anything related.

I have fixed the problem in my project by resolving paths elsewhere and it works fine, just wondered if anyone can shed any light on this?

Thanks!

resolve() follows symlinks, and the python executable created by virtualenv can be a symlink to the “system” Python.

The python in a venv is a symlink, not a copy. resolve() traverses those symlinks to find the name that the link is pointing at.

Path. resolve ( strict=False )
Make the path absolute, resolving any symlinks

$ python3 -m venv myvenv
$ ls -l myvenv/bin/python*
lrwxrwxrwx 1 user user  7 Feb 21 09:46 myvenv/bin/python -> python3
lrwxrwxrwx 1 user user 16 Feb 21 09:46 myvenv/bin/python3 -> /usr/bin/python3
$ ls -l /usr/bin/pyhon3
lrwxrwxrwx 1 root root 9 Mar 13  2020 /usr/bin/python3 -> python3.8

So resolve()ing this path returns the absolute path to the system python (assuming that’s what you created the venv from).

$ myvenv/bin/python -c 'import pathlib; print(pathlib.Path("myvenv").joinpath("bin/python").resolve())'                                                                                               
/usr/bin/python3.8

If you want pathlib to not follow symlinks, use .absolute()