virtualenvwrapper hooks

python
virtual environments
bash
dotfiles
Author

Neil Shephard

Published

July 31, 2024

I’ve written previously about virtualenvwrapper which I use to manage my Python Virtual Environments and mentioned the possibility of using hooks but didn’t go into detail.

Introduction

Just like the various hooks available in Git, virtualenvwrapper also supports hooks that allow scripts to be run in response to various events. These reside under your $VIRTUALENVWRAPPER_HOOK_DIR which by default is the same as your $WORKON_HOME directory and in a typical standard installation will be ~/.virtualenvs.

The available scripts that are recognised are…

  • get_env_details
  • initialize
  • premkvirtualenv
  • postmkvirtualenv
  • precpvirtualenv
  • postcpvirtualenv
  • preactivate
  • postactivate

Each of these is a simple shell script and will start with the scripting language to use e.g. #!/usr/bin/bash or #!/usr/bin/zsh depending on your shell. You can then script the actions you wish to take when the script is executed.

Install minimal requirements

I’m a big fan of dotfiles1, mine are hosted on GitLab, it’s a repository of my configuration files and scripts that I use regularly across multiple computers. Because I’m lazy I wrote a couple of requirements.txt files for installing packages in my virtual environments.

Because I have my dotfiles cloned to the same location on every computer (~/dotfiles) I added the following to the ~/.virtualenvs/postmkvirtualenv 2 which will install all of the packages listed in ~/dotfiles/python/venv_minimal_requirements.txt whenever a create a new virtual environment, whether that is with mkvritualenv or mktmpenv.

pip install --no-cache-dir -r ~/dotfiles/python/venv_minimal_requirements.txt

This ensured the latest versions of each packages listed in ~/dotfiles/python/venv_minimal_requirements.txt were downloaded and installed as the --no-cache-dir prevents using cached versions of packages.

A smarter script

This served me well for a time, but occasionally I found I didn’t want to install any packages in a new virtual environment (most often when testing new branches using mktmpenv) and I’d have to remember to comment out the line in the hook file (~/.virtualenvs/postmkvirtualenv) before creating the environment. Typically though I’d forget to do this and would have to halt installation of required packages, deactivate the environment, then comment it out and create a new environment.

This quickly became irksome.

But ~/.virtualenvs/postmkvirtualenv is just a script and so we can use a bit of scripting knowledge to make it interactive and ask the user if they want to install the packages listed in venv_minimal_requirements.txt. I found a really useful answer on StackOverflow in the How do I prompt for yes/no/cancel input in a Linux shell script that showed several different ways to prompt the user for a response as to whether they want to do something.

I therefore updated my ~/.virtualenvs/postmkvirtualenv to the following which prompts for a numeric response, 1 for Yes and 2 for No and takes the appropriate action, installing using my original invocation of pip if I want to install packages and enter 1 or installing nothing if I enter 2.

#!/usr/bin/zsh
# This hook is sourced after a new virtualenv is activated.


echo "Do you wish to install minimal requirements (from venv_minimal_requirements.txt)? "
select yn in "Yes" "No"; do
  case $yn in
    Yes ) pip install --no-cache-dir -r ~/dotfiles/python/venv_minimal_requirements.txt; break;;
    No ) echo "No packages installed. install packages with 'pip'.\n"; break;;
  esac
done

NB You may want to tweak the opening shebang if you use the Bash shell.

Conclusion

A little bit of shell scripting knowledge can be really powerful when used in conjunction with “hooks”. This is true of virtualenvwrapper as well as of Git and the pre-commit framework.

No matching items

Footnotes

  1. There is a wealth of information on what you can do with your dotfiles but that is an article in itself and I’m yet to write it. A useful set of different aliases you could use can be found here↩︎

  2. Actually I create the script in ~/dotfiles/python/postmkvirtualenv and made a symbolic link at ~/.virtualenv/postmkvirtualenv that points to it so that whenever I update or improve this script it is updated across my computers.↩︎

Reuse

Citation

BibTeX citation:
@online{shephard2024,
  author = {Shephard, Neil},
  title = {Virtualenvwrapper Hooks},
  date = {2024-07-31},
  url = {https://blog.nshephard.dev/posts/virtualenv-hooks/},
  langid = {en}
}
For attribution, please cite this work as:
Shephard, Neil. 2024. “Virtualenvwrapper Hooks.” July 31, 2024. https://blog.nshephard.dev/posts/virtualenv-hooks/.