The question is about shell setup for virtualenvwrapper, an extension to virtualenv (python guide).
Similar questions had been asked many times but with a lot with different answers:
Which is the "best" way to trigger environment setup and function definition script, considering several possible options:
- ~/.profile
- ~./.bash_profile, ~/.zprofile
- ~./bash_login, ~./zlogin (esoteric option)
- ~/.bashrc, ~/.zshrc
The virtualenvwrapper guide states:
"Add three lines to your shell startup file (.bashrc, .profile, etc.) to set the location where the virtual environments should live"
Before considering available options, it is important to consider possible "Use-Cases":
- terminal (console) login (without X, locally)
- ssh remote login (interactive)
- ssh remote command execution (non interactive)
- after a "graphical" login (GDM), opening a terminal (gnome-terminal)
- directly in DE (Gnome), via "desktop" file Exec invocation
- indirectly invoked from xclient (e.g. emacs subprocess)
- stated as cron job for the user
- registered as systemd service (or socket) for non-root user
- indirectly started by a service subprocess (e.g. httpd CGI)
In order to support X graphical login, the only way to set the path is via ~/.profile, that gets sources by /etc/gdm/Xsession, after /etc/profile
While this is the best place for path and environment setting, it fails to define correctly virtualenvwrapper functions ("workon")
The reason is that Xsession is executed under POSIX /bin/sh shell, that is not supported by virtualenvwrapper (bash, zsh, ksh support)
Some distro adopted dash as POSIX shell, while other still rely on POSIX-mode bash invocation.
See
for non bash/zsh/ksh exclusion.
In X logins, using ~/.profile for (manual) environment settings works:
export WORKON_HOME=~/.virtualenvs
export ENV_NAME='myvirtualenv'
export VIRTUAL_ENV="$WORKON_HOME/$ENV_NAME"
export PATH="$VIRTUAL_ENV/bin:$PATH"
unset PYTHON_HOME
the virtualenvwrapper function definition does not work;
source `which virtualenvwrapper.sh`
A alternative could be to put everything in ~/bashrc
export WORKON_HOME=~/.virtualenvs
export ENV_NAME='myvirtualenv'
source `which virtualenvwrapper.sh`
workon $ENV_NAME
But this DOES NOT WORK also:
- X (gnome-shell) does not get initialized, so .desktop files exec command with the "system" environment, not the virtual one.
- the environment set by some process (emacs) is destroyed by ~/.bashrc override
An example:
A better option could be a mixed solution (not so cool ...)
In ~/.profile, manual environment setting
export WORKON_HOME=~/.virtualenvs
export ENV_NAME='myvirtualenv'
export VIRTUAL_ENV="$WORKON_HOME/$ENV_NAME"
export PATH="$VIRTUAL_ENV/bin:$PATH"
unset PYTHON_HOME
In ~/.bash_profile or ~/.zprofile, include POSIX profile and function definition:
[ -f ~/.profile ] && source ~/.profile
[ -f `which virtualenvwrapper.sh` ] && source `which virtualenvwrapper.sh`
In gnome-terminal, enabling the "login-shell" option, the "workon" functions gets defined.
For remote execution it is possible to trigger profile inclusion in this way:
ssh localhost bash --login -c env
Maybe something similar could be done for systemd and cron invocation.
See:
All this configuration stuff looks ugly and hard to maintain. Is it possible a better solution ?