Dzeri, 09-12-2022, Programming
Figuring out how pipenv matches the appropriate python venv with the current project
As I was cleaning up some unused python virtual environments from ~/.local/share/virtualenvs
, I started to wonder, how does pipenv match a folder in this directory with a project directory that could be mounted literally anywhere on the system?
Looking around the source code of pipenv, I came across the _get_virtualenv_hash function, which produces the directory name used in the virtualenvs
directory:
def _get_virtualenv_hash(self, name: str) -> str:
"""Get the name of the virtualenv adjusted for windows if needed
Returns (name, encoded_hash)
"""
def get_name(name, location):
name = self._sanitize(name)
hash = hashlib.sha256(location.encode()).digest()[:6]
encoded_hash = base64.urlsafe_b64encode(hash).decode()
return name, encoded_hash[:8]
clean_name, encoded_hash = get_name(name, self.pipfile_location)
venv_name = "{0}-{1}".format(clean_name, encoded_hash)
...
In essence, pipenv builds a name from the project directory name and the first 8 characters of the sha256 hash of the full path to the Pipfile inside the project. When running pipenv
commands inside a project, it builds this name and checks if a corresponding folder exists in the virtualenvs
directory. If it doesn't exist yet, it is created. This means that if you move your project to some other location, the hash of the path will not match with the old one and a new virtual environment will be created.
One thing left to note is that the directory where all virtual environments are stored is OS-specific. To understand how it is picked, check the get_workon_home method.