deactivate conflict in virtualenvwapper and anaconda
Asked Answered
S

5

12

I'm using virtualenv to switch my python dev env. But when I run workon my_env, I meet such error message:

Error: deactivate must be sourced. Run 'source deactivate'
instead of 'deactivate'.

Usage: source deactivate

removes the 'bin' directory of the environment activated with 'source
activate' from PATH.

After some searches on google, it seems that workon, which is defined in /usr/local/bin/virtualenvwrapper.sh, calls deactivate. And there is a script with the same name is present in Anaconda's bin, so it gets called by workon by mistake.

Any suggestion for working around this conflict?

Scribner answered 18/5, 2015 at 16:16 Comment(0)
S
15

One solution which works for me is to rename deactivate in Anaconda's bin:

mv deactivate conda-deactivate

Spectroheliograph answered 29/10, 2015 at 14:44 Comment(2)
I picked the same name before seeing this answer. +1 for conda-deactivate as new standard!Clump
This is fragile since conda is also using deactivate in several places.Seasoning
P
10

I agree with the comment by @FredrikHedman that renaming scripts in the anaconda/miniconda bin directory has the potential to be fragile. His full post led me to what I feel is a more robust answer. (Thanks!)

Rather than simply throwing away any errors thrown by calling deactivate, we could simply condition that call on whether the function would be called versus the file. As mentioned, virtualenv and virtualenvwrapper create a function named deactivate; the *condas call a script file of the same name.

So, in the virtualenvwrapper.sh script, we can change the following two lines which test for whether deactivate is merely callable:

type deactivate >/dev/null 2>&1
if [ $? -eq 0 ]

with the stricter test for whether it's a shell function:

if [ -n $ZSH_VERSION ] ; then
    nametype="$(type -w deactivate)"
else
    nametype="$(type -t deactivate)"
fi
if [ "${nametype##* }" == "function" ]

This change avoids triggering the spurious error noted in the original question, but doesn't risk redirecting other useful errors or output into silent oblivion.

Note the variable substitution on nametype in the comparison. This is because the output of type -w under zsh returns something like "name: type" as opposed to type -t under bash which returns simply "type". The substitution deletes everything up to the last space character, if any spaces exist, leaving only the type value. This harmlessly does nothing in bash.

(Thanks to @toprak for the zsh test and for the correct flag, type -w, under zsh. I look forward to more cross-shell coding tips!)

As ever, I appreciate constructive feedback and comments!

Parmesan answered 2/2, 2017 at 23:10 Comment(3)
it works, this solution has my vote I agree that conda could be using deactivate in another ways an changes its name not sound great idea, let the conda alone !!Nudibranch
type -t doesn't work in zsh (5.1.1). Updating python -mpip install -U virtualenvwrapper fixed the conflict with pyenv's deactivate for me.Leatherjacket
I get instead the error -bash: type: -w: invalid option, so I had to go back to version before of the edition, i.e. I don't have an else, and instead of nametype="$(type -w deactivate)" I have nametype="$(type -t deactivate)"Anderton
C
3

You can edit /usr/local/bin/virtualenvwrapper.sh to make deactivate point to an absolute path to whatever deactivate it is supposed to be referencing.

Charlie answered 20/5, 2015 at 17:0 Comment(2)
Where is the right deactivate? I used brew to install my virtualenvwrapper. And there are so many "deactivate"s in /usr/local/bin/virtualenvwrapper.sh. Any elegant solution to change the deactivate it use?Scribner
virtualenvwrapper expects deactivate to be a shell function, there is no path to point to.Orthocephalic
B
2

As I do not have enough reputations to add a comment: Thomas Capote's suggestion is fine (thx 4 that), except "zsh" does not have a "-t" option for the build-in command "type". Therefore its necessary to add another conditional statement to get desired result for "nametype":

# Anaconda workaround for "source deactivate" message:
# Start of workaround:
#type deactivate >/dev/null 2>&1
#if [ $? -eq 0 ]
if [ -n $ZSH_VERSION ] ; then
    nametype="$(type -w deactivate)"
else
    nametype="$(type -t deactivate)"
fi
if [ "${nametype##* }" == "function" ]
# End of workaround

Hope it helps other zsh users.

Bowerman answered 1/11, 2017 at 13:53 Comment(1)
Thank you so much, @toprak, for the helpful addition regarding zsh! i will edit my answer to incorporate this and credit you.Parmesan
S
1

In anaconda activate is an executable script located in the anaconda bin directory, but is a function in in virtualenvwrapper.sh. So this is sort of a namespace collision problem, but also a case of overlap in functionality.

Anacondas is a python distribution and – among many other things – has support for dealing with virtual environment via conda env while the virtualenvwrapper is focused on working with different virtual environments. Just renaming the anaconda/bin/activate script is a brittle solution and may break conda.

The code of virtualenvwrapper.sh (function workon) executes deactivate which happens to use the anaconda script. This script returns an error. The workon code then goes on and removes the deactivate name and sources its own deactivate and also creates a deactivate function on the fly.

In summary, it does the right thing and the "error" can be viewed more as a warning. If you want to make it go away you can modify the workon function (search for the line # Deactivate any current environment "destructively")

deactivate
-->
deactivate >/dev/null 2>&1

(I have suggested this change to the virtualenvwrapper maintainer)

Seasoning answered 5/7, 2016 at 8:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.