Skip to main content

Manage Python Environments Faster With Aliases and Functions

·3 mins

If you aren’t regularly wiping and rebuilding your virtual environments, you should be; anyone trying to run your project for the first time will thank you for it. For most folks that’s using python -m venv .venv to create a new one, or conda create if you’re on the conda stack. I do this so frequently that it became my first bash alias. In sh, bash, and most other shells, there’s more than one way to make longer commands shorter, the easiest of which is the alias:

alias so="source .venv/bin/activate"

After running this, when we use so as the first command, it will be replaced with the text source .venv/bin/activate. Remembering to just type so once I cd to a project is much easier to remember and type quickly. If we don’t already have an environment, we usually have to create it:

alias new-venv="python -m venv .venv"

To chain two operations together in bash, we use && to allow the second part to run only if the first one succeeded:

new-venv && so

Beyond that, we usually have to upgrade pip in the new environment

new-venv && so && pip install --upgrade pip wheel

And this chain is so common, I actually have the entire thing under the new-venv name, but as a bash function so it can take arguments:

new-venv() {
	local name=${1:-.venv}
	local python_version=${2:-3}

	python${python_version} -m venv $name \
		&& source $name/bin/activate \
		&& python3 -m pip install --upgrade pip wheel

The usage of this function is like this:


with both arguments optional. The voodoo magic on the first two lines inside the function just says:

  1. Assign the value of the first argument to the name variable, and set it to “.venv” if nothing is passed in
  2. Assign the value of the second parameter to the python_version variable, and set it to “3” if nothing is passed in

Physical savings might only be a few letters, but there’s a real cognitive benefit to building out your most common operations as aliases or functions. You can think at higher levels of operation, with four to five commands clicked together instead of just the current one. Often I go “I call uncle! Let’s try with a fresh environment”

deactivate && rm -rf .venv && new-venv && poetry install

Raymond Hettinger says we have a buffer in our mind of “about five things, plus or minus two”. By reducing the process above to only four steps, even on a bad day I can remember how to do this.

To make sure these aliases/functions are available every time you log in, add them to your “rc” file. For most folks that’s ~/.bashrc, but fish users would use funced and funcsave, zsh users have ~/.zshrc, and on Windows there’s a host of options (I wouldn’t try all this in cmd).

I actually like the funced idea from fish a lot, so I use something similar. This allows me to edit any function in my ~/.bash_functions folder, which is then loaded up using load-funcs (also a function), and that is what gets executed by my ~/.bashrc. This gives me the chance to very quickly save useful snippets like what’s above for later. In particular, instead of looking up the right invocation to install poetry every time, I just tucked it away into the install-poetry function when I first ran it, and now it’s ready for me everywhere I take my dotfiles.