Managing Python Environments Automatically
Working with Python inevitably means managing virtual environments.
I like to automate as much of my workflow as possible, and one common annoyance I’ve encountered arises when editing code with Neovim inside a project managed by uv.
Because uv automatically uses a virtual environment when invoked (e.g. via uv run), opening code inside Neovim can lead to issues if dependencies aren’t installed.
For example, language servers (LSPs) might fail to work correctly.
While this is a fairly niche problem, the convenience of not having to remember to manually activate virtual environments when switching between projects can be a huge time-saver.
For this, I use direnv.
Setting Up Automatic Virtual Environment Loading
Inside $XDG_CONFIG_HOME/direnv/direnvrc I define a function like this:
load_uv_venv() {
if [[ -d ".venv" ]]; then
VIRTUAL_ENV="$(pwd)/.venv"
fi
if [[ -z $VIRTUAL_ENV || ! -d $VIRTUAL_ENV ]]; then
echo "No virtual environment exists. Executing \`uv venv\` to create one."
uv venv
VIRTUAL_ENV="$(pwd)/.venv"
fi
echo "Loading $VIRTUAL_ENV"
PATH_add "$VIRTUAL_ENV/bin"
# optional
export UV_ACTIVE=1 # or VENV_ACTIVE=1
export VIRTUAL_ENV
}
Then, at each project level include the following in your .envrc.
load_uv_venv
Don’t forget to run direnv allow when you change this file.
When leaving the project tree, direnv automatically restores your previous environment (in practice, it undoes any changes made to PATH, removing the virtual environment’s bin directory).
For example:
cd ~/Documents/repos/inpost_demand
direnv: loading ~/Documents/repos/inpost_demand/.envrc
Loading /home/sdysch/Documents/repos/inpost_demand/.venv
direnv: export +UV_ACTIVE +VIRTUAL_ENV ~PATH
❯ which python
/home/sdysch/Documents/repos/inpost_demand/.venv/bin/python
❯ cd
direnv: unloading
❯ which python
/usr/bin/python
This could similarly be adapted for other managers such as conda.