Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to automatically activate virtualenvs when cd'ing into a directory

I have a bunch of projects in my ~/Documents. I work almost exclusively in python, so these are basically all python projects. Each one, e.g. ~/Documents/foo has its own virtualenv, ~/Documents/foo/venv (they're always called venv). Whenever I switch between projects, which is ~10 times a day, I do

deactivate cd .. cd foo source venv/bin/activate 

I've reached the point where I'm sick of typing deactivate and source venv/bin/activate. I'm looking for a way to just cd ../foo and have the virtualenv operations handled for me.

  • I'm familiar with VirtualEnvWrapper which is a little heavy-handed in my opinion. It seems to move all your virtualenvs somewhere else, and adds a little more complexity than it removes, as far as I can tell. (Dissenting opinions welcome!)

  • I am not too familiar with shell scripting. If you can recommend a low-maintenance script to add to my ~/.zshrc that accomplishes this, that would be more than enough, but from some quick googling, I haven't found such a script.

  • I'm a zsh/oh-my-zsh user. oh-my-zsh doesn't seem to have a plugin for this. The best answer to this question would be someone contributing an oh-my-zsh plugin which does this. (Which I might do if the answers here are lackluster.

like image 978
Alex Lenail Avatar asked Jul 20 '17 13:07

Alex Lenail


2 Answers

Add following in your .bashrc or .zshrc

function cd() {   builtin cd "$@"    if [[ -z "$VIRTUAL_ENV" ]] ; then     ## If env folder is found then activate the vitualenv       if [[ -d ./.env ]] ; then         source ./.env/bin/activate       fi   else     ## check the current folder belong to earlier VIRTUAL_ENV folder     # if yes then do nothing     # else deactivate       parentdir="$(dirname "$VIRTUAL_ENV")"       if [[ "$PWD"/ != "$parentdir"/* ]] ; then         deactivate       fi   fi } 

This code will not deactivate the virtualenv even if someone goes into subfolder. Inspired by answers of @agnul and @Gilles.

If the virtualenv is made by pipenv, then please consider this wiki page.

Furthermore, for added security please consider direnv.

like image 151
MS_ Avatar answered Oct 04 '22 08:10

MS_


Put something like this in your .zshrc

function cd() {   if [[ -d ./venv ]] ; then     deactivate   fi    builtin cd $1    if [[ -d ./venv ]] ; then     . ./venv/bin/activate   fi } 

Edit: As noted in comments cd-ing into a subfolder of the current virtual env would deactivate it. One idea could be to deactivate the current env only if cd-ing into a new one, like

function cd() {   builtin cd $1    if [[ -n "$VIRTUAL_ENV" && -d ./venv ]] ; then     deactivate     . ./venv/bin/activate   fi } 

that could still be improved, maybe turning it into a "prompt command" or attempting some prefix matching on the folder names to check there's a virtual env somewhere up the path, but my shell-fu is not good enough.

like image 44
agnul Avatar answered Oct 04 '22 08:10

agnul