Customzing Pyenv Behavior with Hooks
Daan Debie / November 28, 2021
2 min read
I use pyenv to manage different Python versions on my laptop. It also comes with an official plugin that lets you manage virtualenvs through pyenv, which I find very convenient. Basically, virtualenvs are treated as just different Python versions by pyenv.
One thing that bothered me is that, whenever I create a new virtualenv and use
pip in it, I am
inevitably greeted by a message telling me
pip is out-of-date:
WARNING: You are using pip version 21.2.3; however, version 21.3.1 is available. You should consider upgrading via the '~/.pyenv/versions/3.10.0/envs/test/bin/python3.10 -m pip install --upgrade pip' command.
So I end up always having to upgrade pip after creating a new virtualenv. Wouldn’t it be nice if this could be automated?
Turns out, we actually can by leveraging pyenv hooks.
pyenv hooks are scripts that are executed by pyenv whenever certain commands are run. These can be
regular pyenv commands like
pyenv install or
pyenv rehash for example. But what is not
apparent from the pyenv documentation, is that you can also create hooks for plugins, like
You can create a hook by creating a script at the following location:
hook-name here can be any of:
install — which are all regular pyenv
commands — but it can also be a plugin command, like
virtualenv. The filename of the script doesn’t
matter, and neither does the extension. I use
.bash here to make it explicit that this is a bash
script, but pyenv hooks can be written in any language.
To create a hook that upgrades
pip and some other default packages, you can create a new script
mkdir -p $PYENV_ROOT/pyenv.d/virtualenv/ $EDITOR $PYENV_ROOT/pyenv.d/virtualenv/after.bash
$EDITOR is your favorite editor (like
Then add the following contents:
after_virtualenv 'PYENV_VERSION="$VIRTUALENV_NAME" pyenv-exec pip install --upgrade pip setuptools wheel'
after_virtualenv is the command that tells pyenv when to execute the following command. In this
case its defined by the
pyenv virtualenv plugin. First we set the pyenv version to the name
of the virtualenv we just created. This is set by pyenv virtualenv as
$VIRTUALENV_NAME. Then we
pip itself and
That is all there is to it! Now any time you create a new virtualenv using
pyenv virtualenv, the
aforementioned packages will be automatically upgraded after the virtualenv was created.