Jun 18, 2019

Managing Python environments with direnv

A few months ago I discovered direnv and was surprised how I got along so well with out it. From the website, direnv ” allows project-specific environment variables without cluttering the ~/.profile file.” I used it to make aliases that only exist inside a project, as well as a path to project-specific scripts and environment variables. Then I discovered that you can manage Python environments with it and my eyes opened up to all the power you could do. In reality, it makes this popular post unnecessary since direnv does all the work for you.

The direnv project has a good wiki doc here but it’s long and has a lot of scenarios – I’ll put in here what worked for me. This is all very specific to Python and virtualenv, but it gives a good indication of what all you can do with direnv, regardless of what language you are using.

First you have to install direnv with your favorite package manager. Then enabling it is easy – for me, it was adding the following line to the very end~/.zshrc:

 eval "$(direnv hook zsh)"


There are hooks for bash and other shells as well.

Then I had a one-time setup in the main direnv file. On my Mac, it is in ~/.config/direnv/direnvrc

use_python() {
    if [ -n "$(which pyenv)" ]; then
        local pyversion=$1
        pyenv local ${pyversion}

layout_virtualenv() {
    local pyversion=$1
    local pvenv=$2
    if [ -n "$(which pyenv virtualenv)" ]; then
        pyenv virtualenv --force --quiet ${pyversion} ${pvenv}-${pyversion}
    pyenv local --unset

layout_activate() {
    if [ -n "$(which pyenv)" ]; then
        source $(pyenv root)/versions/$1/bin/activate

And then in each project directory, I make a .envrc file and add the following

show_virtual_env() {
  if [[ -n "$VIRTUAL_ENV" && -n "$DIRENV_DIR" ]]; then
    echo "($(basename $VIRTUAL_ENV))"

pyversion=3.7.2 # your python version
pvenv=my-nifty-project # you project name or what you want to call you virtual env

use python ${pyversion}
# Create the virtualenv if not yet done
layout virtualenv ${pyversion} ${pvenv}
# activate it
layout activate ${pvenv}-${pyversion}

And then, in your terminal, go to you project directory. If you setup direnv correctly (and it’s a one-liner), then you will see a message telling you to allow the changes in your .envrc. Just type direnv allow and, well, that’s it. direnv will see that you don’t have your virutalenv setup in that folder and will automatically set it up. After the initial time, it will automatically register and be enabled for you.

Again, this is just the tip of the iceberg of what you can do with direnv. It’s saved me a lot of headaches. What kind of creative uses can you implement into your workflow?

About the Author

Mike Hostetler profile.

Mike Hostetler

Principal Technologist

Mike has almost 20 years of experience in technology. He started in networking and Unix administration, and grew into technical support and QA testing. But he has always done some development on the side and decided a few years ago to pursue it full-time. His history of working with users gives Mike a unique perspective on writing software.

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Blog Posts
Managing your Helm deployments with Helmfile
As we’ve been using Kubernetes to build software delivery platforms for our clients, we’ve found Helm to be a reasonable solution to templating and managing deployments to Kubernetes.  Although templating alternatives such as Kustomize have […]
AWS CodeBuild Test Reports for Gradle builds
Although AWS documentation has instructions for adding Test Reports for a maven build they currently lack instructions for a gradle build. You can find the maven instructions here: https://aws.amazon.com/blogs/devops/test-reports-with-aws-codebuild/ Assuming you have your gradle wrapper […]
Structuring SwiftUI Previews for API Calls
SwiftUI, together with Combine and Xcode 11+, provide a powerful toolset for quickly creating an app with a native UI. In Xcode 11+, the preview pane was introduced in order to provide live snapshots of […]
Seamlessly Integrating Micro Apps with iFrame
A recent client wanted to upgrade a small portion of their legacy application with a more modern UI and extra functionality, like fuzzy text search. There are a few approaches to incremental upgrades of legacy […]