activating virtualenv with direnv doesn't activate virtualenv

10k Views Asked by At

I'm using direnv to source my virtualenv when I change into the directory.

/project
   .envrc
   /env <--- my virtualenv

.envrc

source env/bin/activate

When I change directory into /project I get the output:

direnv: loading .envrc
direnv: export +VIRTUAL_ENV -PS2 ~PATH

It prepends the env directory to my PATH environment variable so when I run which python and which pip both point to python and pip that's in my env directory

=> which python
/USER/project/env/bin/python
=> which pip
/USER/project/env/bin/pip

However it doesn't seem to run source env/bin/activate as I expect it to. I expect it to activate my virtualenv by adding the virtualenv name (env) to my CLI prompt and give access to the deactivate command, neither of that happens. Is there something I'm misunderstanding about how direnv and virtualenv work? I'm new to python so I'm not sure if there are existing tools to do something like this.

2

There are 2 best solutions below

2
On

I think it's important to understand how direnv works to form a proper mental model first; direnv doesn't load the .envrc directly in the current shell. Instead, it starts a new bash shell, executes the .envrc in there, records the changes in environment and exports the diff bash into the current shell.

What is happening here is that:

virtualenv is using $PS1 to set the prompt. This is a local variable and thus not re-exported. direnv also filters PS1 because it causes segfaults on the old macOS bash when it's unset.

The deactivate() function is not exported from the bash sub-shell as it's not an environment variable.

In practice the activation worked as you noticed. python is in the right path and running pip or easy_install is going to install things in the virtualenv. deactivation is not necessary as direnv will automatically unload the environment when cd-ing out of the directory.

To restore the custom prompt, there is more info available on the wiki: https://github.com/direnv/direnv/wiki/Python#restoring-the-ps1

1
On

There is a "hidden" feature to do what you want in direnv. You have to take a look at the toolbox that is loaded by direnv for you to use in the .envrc files. You can use the layout command with python (layout python3) to activate a virtualenv on entering the dir, and deactivating it when exiting the directory. It will even take care of creating the virtualenv the first time.

Also take a look at source_up that keep loading .envrc files higher in the file system. I start all my projects by creating a .envrc file with the following:

layout python3
source_up

This will create, activate and deactivate a python virtualenv automatically, and keep on reading variables from higher-level .envrc files. Environement variables for the current project only will go in the local .envrc.