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!

1 Like

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

2 Likes

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()

1 Like