【问题标题】:deactivate conflict in virtualenvwapper and anaconda停用 virtualenvwrapper 和 anaconda 中的冲突
【发布时间】:2015-07-30 06:02:57
【问题描述】:

我正在使用 virtualenv 来切换我的 python 开发环境。但是当我运行workon my_env 时,我遇到了这样的错误信息:

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.

在google上搜索了一下,似乎是/usr/local/bin/virtualenvwrapper.sh中定义的workon调用了deactivate。而且Anaconda的bin里有一个同名的脚本,所以被workon误调用了。

有解决此冲突的建议吗?

【问题讨论】:

    标签: python virtualenv anaconda virtualenvwrapper


    【解决方案1】:

    我同意 @FredrikHedman 的评论,即重命名 anaconda/miniconda bin 目录中的脚本可能会变得脆弱。他的完整帖子使我得到了我认为更可靠的答案。 (谢谢!)

    与其简单地丢弃调用deactivate 引发的任何错误,我们还可以简单地以函数文件 是否会被调用为条件。如前所述, virtualenv 和 virtualenvwrapper 创建了一个名为 deactivate 的函数; *condas 调用同名的脚本文件。

    因此,在virtualenvwrapper.sh 脚本中,我们可以更改以下两行来测试deactivate 是否仅仅是可调用的:

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

    对是否为 shell 函数进行更严格的测试:

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

    此更改避免触发原始问题中指出的虚假错误,但不会冒将其他有用错误重定向或输出到无声遗忘的风险。

    注意比较中nametype 上的变量替换。这是因为type -wzsh 下的输出返回类似于“name: type”的内容,而type -tbash 下的输出则仅返回“type”。如果存在任何空格,替换将删除最后一个空格字符之前的所有内容,只留下类型值。这在bash 中无害。

    (感谢@toprak 的zsh 测试和正确的标志type -w,在zsh 下。我期待更多跨shell 编码技巧!)

    一如既往,我非常感谢建设性的反馈和 cmets!

    【讨论】:

    • 它有效,这个解决方案有我的投票我同意 conda 可以以其他方式使用 deactivate 更改它的名称听起来不是个好主意,让 conda 一个人!
    • type -t 在 zsh (5.1.1) 中不起作用。更新 python -mpip install -U virtualenvwrapper 修复了与 pyenv 为我停用的冲突。
    • 我得到了错误-bash: type: -w: invalid option,所以我不得不回到该版本之前的版本,即我没有else,而不是nametype="$(type -w deactivate)"我有@ 987654343@
    【解决方案2】:

    由于我没有足够的声誉来添加评论: Thomas Capote 的 建议很好(谢谢 4),除了 "zsh" 没有用于内置命令 "type" 的 "-t" 选项。因此有必要添加另一个条件语句以获得“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
    

    希望它可以帮助其他 zsh 用户。

    【讨论】:

    • 非常感谢@toprak 对 zsh 的帮助!我将编辑我的答案以纳入这一点并感谢您。
    【解决方案3】:

    在 anaconda activate 是一个可执行脚本,位于 anaconda bin 目录中,但在 virtualenvwrapper.sh 中是一个函数。所以这是一种命名空间冲突问题,也是功能重叠的情况。

    Anacondas 是一个 python 发行版,除其他外,它支持通过conda env 处理虚拟环境,而 virtualenvwrapper 专注于处理不同的虚拟环境。只是重命名 anaconda/bin/activate 脚本是一个脆弱的解决方案,可能会破坏conda

    virtualenvwrapper.sh(函数workon)的代码执行deactivate,恰好使用了anaconda脚本。此脚本返回错误。然后workon 代码继续并删除deactivate 名称并获取它自己的deactivate 并动态创建deactivate 函数。

    总而言之,它做了正确的事情,“错误”可以更多地视为警告。如果你想让它消失你可以修改workon函数(搜索# Deactivate any current environment "destructively"这一行)

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

    (我已向 virtualenvwrapper 维护者建议此更改)

    【讨论】:

      【解决方案4】:

      对我有用的一个解决方案是在 Anaconda 的 bin 中重命名 deactivate

      mv deactivate conda-deactivate

      【讨论】:

      • 在看到这个答案之前我选择了相同的名字。 +1 conda-deactivate 作为新标准!
      • 这很脆弱,因为 conda 在多个地方也使用了 deactivate。
      【解决方案5】:

      您可以编辑 /usr/local/bin/virtualenvwrapper.sh 以使 deactivate 指向它应该引用的任何 deactivate 的绝对路径。

      【讨论】:

      • 正确的停用在哪里?我使用 brew 来安装我的 virtualenvwrapper。在 /usr/local/bin/virtualenvwrapper.sh 中有很多“停用”。任何优雅的解决方案来改变它使用的停用?
      • virtualenvwrapper 期望 deactivate 是一个 shell 函数,没有指向的路径。
      猜你喜欢
      • 2018-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多