Reputation: 827
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.
Upvotes: 7
Views: 12263
Reputation: 816
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
.
Upvotes: 11
Reputation: 812
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
Upvotes: 15