首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从bash脚本中临时绕过python虚拟环境?

如何从bash脚本中临时绕过python虚拟环境?
EN

Stack Overflow用户
提问于 2016-05-13 18:09:23
回答 2查看 1.4K关注 0票数 3

我确实有一个bash脚本,它需要在系统上安装一些Python包,而不是在执行脚本时被激活的虚拟环境。

这个脚本是由已经激活python虚拟环境的人调用的,我确实希望确保对于少数命令,我不会使用它。

我尝试使用deactivate命令,但它似乎不可用,即使bash检测到虚拟环境(存在VIRTUAL_ENV变量)。

顺便提一句,我不想永久地禁用虚拟环境。我只想在它外面运行几个命令。我该怎么做?

EN

回答 2

Stack Overflow用户

发布于 2016-05-13 18:15:34

如果在启动脚本之前激活

如果在父shell中执行activate步骤,而不是在运行脚本的shell实例中执行该步骤,则非导出变量和函数在其运行时不可用。

要完全明确定义:

代码语言:javascript
复制
source my-virtualenv/bin/activate # this runs in the parent shell

./my-shell-script # the shell script itself is run in a child process created by
                  # fork()+execve(); does not inherit shell variables / functions, so
                  # deactivate WILL NOT WORK here.

(source my-shell-script) # creates a subshell with fork(), then directly invokes
                         # my-shell-script inside that subshell; this DOES inherit shell
                         # variables / functions, and deactivate WILL WORK here.

你有三个选择:

  • 在启动脚本deactivate之前,从父shell 导出函数及其依赖项。 如下所示,如下所示: 源my-virtualenv/bin/activate VIRTUAL_ENV VIRTUAL_ENV ${!_OLD_VIRTUAL_@}导出-f禁用-f 您可以选择为您定义一个激活函数,如下所示:将其放入您的.bashrc activate() { source "$1"/bin/activate &{exportVIRTUAL_ENV${{_OLD_VIRTUAL_@}导出-f deactivate }}# ...and中,然后激活虚拟then,如下所示:激活_OLD_VIRTUAL_@
  • 脚本中的猜测一下以前的Python环境是什么样的。 由于明显的原因,这是不可靠的;但是,由于virtualenv不导出包含原始PYTHON_HOME的shell变量,该信息对子进程shell根本不可用;因此,猜测是可用的最佳选择: best_guess_deactivate() {如果[ $VIRTUAL_ENV && $PATH =~ (^$PATH:)“$ VIRTUAL_ENV /bin”($|:) ];那么PATH=${PATH%:$VIRTUAL_ENV/bin“} PATH=${PATH#"$VIRTUAL_ENV/bin:"} PATH=${PATH//”:$PATH=$_ENV/bin:“/} unset PYTHONHOME VIRTUAL_ENV} fi } 在有限范围内的...used,如: run_python_code_in_virtualenv_here (best_guess_deactivate;run_python_code_outside_virtualenv_here) run_python_code_in_virtualenv_here
  • 在第一次来源于activate的shell的分叉子程序中运行脚本,没有插入的exec()调用 也就是说,与使用:New实例调用脚本作为常规子进程不同,它不继承非导出(又称常规shell)变量。/my- shell - script .将其源到当前shell的分叉副本中,现有shell实例的asForked副本确实继承变量(source ./my-shell-script)...or,如果您信任它在执行后不扰乱状态(我不建议)将控制权交给交互式shell,简单地说:可能是一个不好的想法来源。//my脚本所有这些方法都有一些风险:因为它们不使用execve调用,所以它们不尊重脚本上任何一个shebang行,所以如果它是专门为ksh93、zsh或另一个与您交互使用的shell不同的shell编写的,它们很可能会行为不当。

如果在脚本中激活

最有可能的情况是,您正在运行deactivate的shell不是fork()ed的直接子程序(没有插入的exec-family调用),而是继承了由该脚本创建的函数或(非导出的) shell变量。

避免这种情况的一种方法是在deactivate脚本来源的shell中导出activate函数,如下所示:

代码语言:javascript
复制
printf 'Pre-existing interpreter: '; type python

. venv-dir/bin/activate

printf 'Virtualenv interpreter: '; type python

# deactivate can be run in a subshell without issue, scoped to same
printf 'Deactivated-in-subshell interpreter: '
( deactivate && type python ) # this succeeds

# however, it CANNOT be run in a child shell not forked from the parent...
printf 'Deactivated-in-child-shell (w/o export): '
bash -c 'deactivate && type python' # this fails

# ...unless the function is exported with the variables it depends on!
export -f deactivate
export _OLD_VIRTUAL_PATH _OLD_VIRTUAL_PYTHONHOME _OLD_VIRTUAL_PS1 VIRTUAL_ENV

# ...after which it then succeeds in the child.
printf 'Deactivated-in-child-shell (w/ export): '
bash -c 'deactivate && type python'

我的上述产出如下:

代码语言:javascript
复制
Pre-existing interpreter: python is /usr/bin/python
Virtualenv interpreter: python is /Users/chaduffy/test.venv/bin/python
Deactivated-in-subshell interpreter: python is /usr/bin/python
Deactivated-in-child-shell (w/o export): bash: deactivate: command not found
Deactivated-in-child-shell (w/ export): python is /usr/bin/python

假设您已经修复了这个问题,那么让我们再一次使用子subshell进行范围禁用,使其成为临时的:

代码语言:javascript
复制
. venv-dir/activate

this-runs-in-venv

# minor performance optimization: exec the last item in the subshell to balance out
# ...the performance cost of creating that subshell in the first place.
(deactivate; exec this-runs-without-venv)

this-runs-in-venv
票数 6
EN

Stack Overflow用户

发布于 2016-05-13 18:18:00

您可以始终直接引用全局Python:

代码语言:javascript
复制
/usr/bin/python2.7 -E my_python_command

如果您担心这样的路径不可靠,您可以:

  • 在安装时将Python配置在唯一、安全、静态的位置,并引用
  • 调用不在虚拟环境中的子subshell。
  • 为您的虚拟Python可执行文件使用一个备用名称,这样它就不会在路径上发生冲突。即。虚拟Python将是python虚拟的,python仍然会导致全局安装。

然后就会是这样:

代码语言:javascript
复制
python -E my_command # global  
python-virtual my_command # virtual
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37216673

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档