Tags
I have automated my process to create virtual environments in my python projects, here is how I did it.
I've really been digging my new tmux session management setup. Now I have leveled it up by adding direnv to my workflow. It will execute a shell script whenever I cd into a directory. One thing I wanted to add to this was, automatic activation of python environments whenever I cd into a directory, or create a new environment if one does not exist.
https://waylonwalker.com/tmux-nav-2021/
Direnv
You can learn more about direnv on their website. There are several libraries that seem to do a similar concept, run a bash script when I cd into a directory direnv is the one that I chose to use, but you can likely do the same concept in other ones.
Installation
direnv is in many package repos, or can be installed from binary builds with a one liner. See their installation instructions for more information.
curl -sfL https://direnv.net/install.sh | bash
.envrc
direnv works by executing the contents of known safe .envrc
files. Here are
some of the basic commands to get you started.
# edit or create a new .envrc and flag it as allowed direnv edit . # flag a .envrc file as allowed or not direnv allow . direnv deny . # reexecute a .envrc direnv reload
Conda
I most often use conda to manage my virtual environments. I dont use it to
conda install
packages, but I really like the convenience of combinging the
python interpreter with the environment.
conda create -n my-project python=3.9 -y
every time I start a new project I need to create a new environment
conda activate my-project # or source depending on if conda init has been ran on the system source activate my-project
every subsequent time I start work in that project I need to remember to activate
lazy
I'll admit that sometimes I get lazy and will use an existing environment with similar dependencies. This kind of works in a pinch, but almost always I need more packages and start trampling in that other projects environment.
naming the environment
Since I want this process to be easily automated I chose to name my
environments after the name of the directory the project is in. In bash we can
get the current directory with $PWD
, and trim it to just the directory name
with the basename
command.
basename $PWD
this will return the name of the current working directory
condanew
I reates a short bash function that will create a new conda environment, activate it, and install anything extra that the project needs.
condanew() { conda create -n $(basename $PWD) python=3.8 -y source activate $(basename $PWD) pip install lolcat }
This will create a new python environment named after the current directory.
project install
Often I will modify the condanew function to install project specific things.
I leverage editable installs of projects I am working on quite extensively,
that's what the -e
is.
condanew() { conda create -n $(basename $PWD) python=3.8 -y source activate $(basename $PWD) pip install -e ".[dev]" # or pip install -r requirements.txt }
Bash error handling
I dive deeper into this subject in this post about creating reusable-bash scripts. But to auto create the environment I am going to try to activate. If it fails, create a new environment based on the name of the project.
https://waylonwalker.com/reusable-bash/#error-handling
source activate $(basename $PWD) || condanew
Try to activate the environment, if it fails make a new one.
Final Result
Conda
direnv edit .
#!/bin/bash # shortcut for creating new conda environments based on the current working directory condanew() { conda create -n $(basename $PWD) python=3.8 -y source activate $(basename $PWD) pip install lolcat } echo $(basename $PWD) | lolcat source activate $(basename $PWD) || condanew
Venv
Here is a modified version using venv from the standard library.
#!/bin/bash # shortcut for creating new virtual environments venvnew() { python -m venv .venv source .venv/bin/activate pip install lolcat } echo $(basename $PWD) | lolcat source .venv/bin/activate || venvnew