Automatic Conda Environments
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
I have automated my process to create virtual environments in my python projects, here is how I did it.
Date: March 22, 2021
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
```