Automating Python Virtual Environments with Zsh on macOS
Automating Python Virtual Environments with Zsh on macOS
Managing Python virtual environments can be tedious - having to manually activate and deactivate them as you move between projects. I decided to create a script that will automatically activate virtual environment. When you cd
into a directory containing a .venv
folder. When you leave, it will deactivate it.
Installing Zsh
While macOS comes with zsh as the default shell since Catalina (10.15), you may want to ensure you have the latest version. The easiest way to install or update zsh is using Homebrew:
# Install Homebrew if you haven't already
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Install zsh
brew install zsh
Installing Oh My Zsh (Optional but Recommended)
Oh My Zsh is a framework for managing your zsh configuration. It comes with helpful plugins and themes:
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
Configuring Automatic Virtual Environment Activation
Now we’ll set up the automatic virtual environment activation. Add the following code to your ~/.zshrc
file:
#---------------------------------------------- chpwd pyvenv ---
python_venv() {
MYVENV=./.venv
# when you cd into a folder that contains $MYVENV
[[ -d $MYVENV ]] && source $MYVENV/bin/activate > /dev/null 2>&1
# when you cd into a folder that doesn't
[[ ! -d $MYVENV ]] && deactivate > /dev/null 2>&1 || true
}
autoload -U add-zsh-hook
add-zsh-hook chpwd python_venv
python_venv
Let’s break down what this script does:
python_venv()
- Defines a function that checks for and manages virtual environmentsMYVENV=./.venv
- Sets the virtual environment directory name (change this if you use a different name)[[ -d $MYVENV ]]
- Checks if the .venv directory existssource $MYVENV/bin/activate
- Activates the virtual environment if founddeactivate
- Deactivates any active virtual environment when leaving a project directoryadd-zsh-hook chpwd python_venv
- Runs our function whenever we change directories
Testing the Setup
- First, source your updated
.zshrc
:
source ~/.zshrc
- Create a test project with a virtual environment:
# Create a test directory
mkdir ~/test-venv
cd ~/test-venv
# Create a virtual environment
python -m venv .venv
- Test the automatic activation:
# Move out of the directory
cd ~
# Notice the virtual environment is deactivated
# Move back into the test directory
cd ~/test-venv
# The virtual environment should automatically activate
You should see your prompt change to indicate the virtual environment is active when entering the directory, and return to normal when leaving it.
Troubleshooting
If the automatic activation isn’t working:
- Make sure zsh is your default shell:
echo $SHELL
# Should output /bin/zsh
- Check that the function is loaded:
type python_venv
# Should show the function definition
- Verify your virtual environment structure:
ls -la .venv/bin/activate
# Should show the activation script
Additional Tips
- If you use a different virtual environment directory name, modify the
MYVENV
variable in the script. - Add
export VIRTUAL_ENV_DISABLE_PROMPT=1
to your.zshrc
if you want to use your own prompt styling. - Consider adding the following to your global
.gitignore
:
echo ".venv" >> ~/.gitignore_global
git config --global core.excludesfile ~/.gitignore_global
Conclusion
With this setup, you can seamlessly work across multiple Python projects without manually managing virtual environments. The shell takes care of activation and deactivation as you navigate your filesystem, making your development workflow more efficient.
Remember to create your virtual environments with the name .venv
in your project roots to take advantage of this automation. Happy coding!