'how to deactivate virtualenv from a bash script
I'm a novice in shell scripting, but I want to make a bash script for activate/deactivate a virtual enviroment using virtualenv. Then I want to use this script like a service in Ubuntu copying it inside /etc/init.d folder.
In my script, I have a variable like this:
VENV=/opt/odoo/odoo_server/venv_oddo/bin
This variable represents the bin path in my virtual enviroment.
Inside the script, I can activate the virtual enviroment with this statement:
. ${VENV}/activate
This is possible because activate is a file inside bin directory in the virtual enviroment.
But I don't know the statement to use in my script to deactivate my virtual enviroment.
I can't do this: . ${VENV}/deactivate
The problem is that doesn't exist a file named deactivate, but deactivated is a function inside the bin/activate file in the virtual enviroment.
Solution 1:[1]
It'll be hard to make a service like that useful.
. ${VENV}/activate # note the dot
or
source ${VENV}/activate
will source the activate
script, i.e. run its contents as if they were part of the shell or script where you source them. virtualenvironment
's activate
is designed for this usage. In contrast, just executing the script normally with
${VENV}/activate # note: NO dot and NO 'source' command
will run its content in a subshell and won't have any useful effect.
However, your service script will already run in a subshell of its own. So except for any python commands you run as part of the service start process, it won't have any effect.
On the plus side, you won't even have to care about de-activating the environment, unless you want to run even more python stuff in the service start process, but outside of your virtualenv.
Solution 2:[2]
Just deactivate
. It will work in the script as well as in command line, as long as you're using bash.
Edit: also in most cases it is a better idea to spell full python path in your scripts and services. It is stateless, more portable and works pretty much everywhere. So instead of doing
. $VENV/bin/activate
/path/to/my/script.py --parameters
it is usually preferable to do
$VENV/bin/python /path/to/my/script --parameters
Trust me, it will save you debugging time)
Solution 3:[3]
The deactivate
"command" provided by virtualenvwrapper
is actually a shell function, likewise so for workon
. If you have a virtual env active, you can list the names of these functions with typeset -F
.
In order to use them in a script, they need to be defined there, because shell functions do not propagate to child shells.
To define these functions, source the virtualenvwrapper.sh
script in the shell script where you intend to invoke these functions, e.g.:
source $(which virtualenvwrapper.sh)
That allows you to invoke these functions in your shell script like you would do in the shell:
deactivate
Update: What I described works for the other functions provided by virtualenvwrapper (e.g. workon
). I incorrectly assumed it would work also for deactivate, but that one is a more complicated case, because it is a function that will be defined only in the shell where workon
or activate
was run.
Solution 4:[4]
copy deactivate code in ${VENV}/activate.
paste your ~/.bashrc
deactivate() {
# reset old environment variables
if [ -n "$_OLD_VIRTUAL_PATH" ] ; then
PATH="$_OLD_VIRTUAL_PATH"
export PATH
unset _OLD_VIRTUAL_PATH
fi
if [ -n "$_OLD_VIRTUAL_PYTHONHOME" ] ; then
PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME"
export PYTHONHOME
unset _OLD_VIRTUAL_PYTHONHOME
fi
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "$BASH" -o -n "$ZSH_VERSION" ] ; then
hash -r
fi
if [ -n "$_OLD_VIRTUAL_PS1" ] ; then
PS1="$_OLD_VIRTUAL_PS1"
export PS1
unset _OLD_VIRTUAL_PS1
fi
unset VIRTUAL_ENV
if [ ! "$1" = "nondestructive" ] ; then
# Self destruct!
unset -f deactivate
fi
}
run command.
$ $VENV/activate
$ deactivate
I have selectively used without problems python 2.7 and python 3.5 in this way.
I want to know the reason for the negative evaluation.
Solution 5:[5]
If you only need to programatically disable / change virtualenv, you can use a shell function instead of a shell script. For example, put at the end of your ~/.bashrc
or ~/.bash_aliases
(if you have it set up) or ~/.zshrc
or ~/.zsh_aliases
(if you use zsh
):
function ch() {
# change this to your directory
cd ~/git-things/my_other_py_project
# this works, as a shell function won't spawn a subshell as the script would
deactivate
# re-source to change the virtualenv (my use case; change to fit yours)
source .venv-myotherpyproject/bin/activate
}
Restart the shell or re-source the file you changed with source ~/.zsh_aliases
and use the command ch
to execute the function.
Solution 6:[6]
Somehow deactivate
also can't be found in my case (usually I work under far2l inside bash). I use the solution:
unset VIRTUAL_ENV & deactivate
After that pip -V
is showing path in .local.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | |
Solution 4 | |
Solution 5 | Iacchus |
Solution 6 | Unreal Qw |