When you work a lot with Python venvs, and thus have a lot of them sprinkled over your home directory, then remembering to activate the right one can be a source of problems, and is tedious at best. But there is a solution to automate that chore – that's what we have those boxes full of electronics for, after all.

Meet autoenv

Consider this shell session and especially watch what happens to the prompt.

jhe@workstation:~$ which python
/usr/bin/python
jhe@workstation:~$ cd src/github/rituals/
(rituals)jhe@workstation:~/src/github/rituals$ which python
/home/jhe/src/github/rituals/.venv/rituals/bin/python

It's Magic!

The magic wand was originally crafted by Kenneth Reitz, and can be found on GitHub.

Installing autoenv

To get a working installation, the easiest way is to directly use a git checkout as follows:

mkdir -p ~/.local
test -d ~/.local/autoenv \
    || git clone "https://github.com/kennethreitz/autoenv.git" \
                 ~/.local/autoenv
echo >>~/.bash_aliases ". ~/.local/autoenv/activate.sh"
. ~/.local/autoenv/activate.sh

That's all there is to it. Now you just have to add a .env file to your project, like in this example.

Security Considerations

If you're afraid that the cd command is wrapped by a bash function, the following shows that you need not fear, since that function isn't exported to any scripts you run.

(rituals)jhe@workstation:~/src/github/rituals$ bash <<<"pwd; \
    cd $PWD/../time-tunnel; pwd; which python"
/home/jhe/src/github/rituals
/home/jhe/src/github/time-tunnel
/home/jhe/src/github/rituals/.venv/rituals/bin/python

This pretty much restricts the modified cd to interactive use. Sub-shells behave differently, again that's what you'd expect working at the prompt.

(rituals)jhe@workstation:~/src/github/rituals$ ( pwd; \
    cd $PWD/../time-tunnel; pwd; which python )
/home/jhe/src/github/rituals
/home/jhe/src/github/time-tunnel
/home/jhe/src/github/time-tunnel/.venv/time-tunnel/bin/python

If at any time you need the original command on the prompt, just use command cd … or builtin cd ….

Also, nobody can inject code into your shell just so, see what happens if we stumble over a new or modified .env file the first time:

(rituals)jhe@workstation:~/src/github/rituals$ cd .
(rituals)jhe@workstation:~/src/github/rituals$ echo >>.env
(rituals)jhe@workstation:~/src/github/rituals$ cd .
autoenv:
autoenv: WARNING:
autoenv: This is the first time you are about to source /home/jhe/src/github/rituals/.env:
autoenv:
autoenv:     --- (begin contents) ---------------------------------------
autoenv:     # autoenv script (https://github.com/kennethreitz/autoenv)
autoenv:     test \! -f .venv/$(basename $(pwd))/bin/activate || . .venv/$(basename $(pwd))/bin/activate
autoenv:     
autoenv:
autoenv:     --- (end contents) -----------------------------------------
autoenv:
autoenv: Are you sure you want to allow this? (y/N) y

Now you have all the information to decide whether this is something you'd like to use or not.

I do, but YMMV. 🤔