确定Python是否在virtualenv中运行

Determine if Python is running inside virtualenv

是否可以确定当前脚本是否在virtualenv环境中运行?


AFAIK检查这一点的最可靠方法(以及在virtualenv和pip内部使用的方式)是检查是否存在sys.real_prefix

1
2
3
4
import sys

if hasattr(sys, 'real_prefix'):
    #...

在virtualenv中,sys.prefix指向virtualenv目录,sys.real_prefix指向系统Python的"真实"前缀(通常是/usr/usr/local或某些此类)。

在virtualenv之外,sys.real_prefix不应该存在。

使用VIRTUAL_ENV环境变量不可靠。它由virtualenv activate shell脚本设置,但是通过直接运行virtualenv的bin/(或Scripts)目录中的可执行文件,可以在不激活的情况下使用virtualenv,在这种情况下,$VIRTUAL_ENV将不会被设置。


尝试使用pip -V(注意大写字母V)

如果您正在运行虚拟环境。它将显示env。的位置路径。


这是Carl Meyer接受的答案的改进。它适用于Python 3和2的virtualenv以及Python 3中的venv模块:

1
2
3
4
5
6
import sys


def is_venv():
    return (hasattr(sys, 'real_prefix') or
            (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix))

sys.real_prefix的检查涵盖了virtualenv,非空sys.base_prefixsys.prefix的相等性涵盖了venv。

考虑使用如下函数的脚本:

1
2
3
4
if is_venv():
    print('inside virtualenv or venv')
else:
    print('outside virtualenv or venv')

以下调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ python2 test.py
outside virtualenv or venv

$ python3 test.py
outside virtualenv or venv

$ python2 -m virtualenv virtualenv2
...
$ . virtualenv2/bin/activate
(virtualenv2) $ python test.py
inside virtualenv or venv
(virtualenv2) $ deactivate

$ python3 -m virtualenv virtualenv3
...
$ . virtualenv3/bin/activate
(virtualenv3) $ python test.py
inside virtualenv or venv
(virtualenv3) $ deactivate

$ python3 -m venv venv3
$ . venv3/bin/activate
(venv3) $ python test.py
inside virtualenv or venv
(venv3) $ deactivate

检查$VIRTUAL_ENV环境变量。

$VIRTUAL_ENV环境变量包含虚拟环境在活动虚拟环境中的目录。

1
2
3
>>> import os
>>> os.environ['VIRTUAL_ENV']
'/some/path/project/venv'

运行deactivate /离开虚拟环境后,$VIRTUAL_ENV变量将被清除/清空。 Python将引发KeyError,因为环境变量未设置。

1
2
3
4
5
6
7
>>> import os
>>> os.environ['VIRTUAL_ENV']
Traceback (most recent call last):
  File"<stdin>", line 1, in <module>
  File"/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/os.py", line 678, in __getitem__
    raise KeyError(key) from None
KeyError: 'VIRTUAL_ENV'

这些相同的环境变量检查当然也可以在Python脚本之外的shell中完成。


根据http://www.python.org/dev/peps/pep-0405/#specification上的virtualenv pep,您可以使用sys.prefix而不是os.environ ['VIRTUAL_ENV']。

sys.real_prefix在我的virtualenv中不存在,与sys.base_prefix相同。


您可以执行which python并查看它是否指向虚拟环境中的那个。


要检查你的内部Virtualenv:

1
2
3
4
5
6
import os

if os.getenv('VIRTUAL_ENV'):
    print('Using Virtualenv')
else:
    print('Not using Virtualenv')

您还可以获得有关您的环境的更多数据:

1
2
3
4
5
6
import sys
import os

print(f'Python Executable: {sys.executable}')
print(f'Python Version: {sys.version}')
print(f'Virtualenv: {os.getenv("VIRTUAL_ENV")}')


我经常使用几个Anaconda安装的虚拟环境(venv)。此代码段/示例使您可以确定您是否在venv(或您的系统环境)中,并且还需要特定的venv用于您的脚本。

添加到PYTHON SCRIPT(代码片段):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# ----------------------------------------------------------------------------
# Want script to run in Python 3.5 (has required installed OpenCV, imutils, ... packages):
import os

# First, see if we are in a conda venv { py27: Python 2.7 | py35: Python 3.5 | tf: TensorFlow | thee : Theano }
try:
   os.environ["CONDA_DEFAULT_ENV"]
except KeyError:
   print("\tPlease set the py35 { p3 | Python 3.5 } environment!
"
)
   exit()

# If we are in a conda venv, require the p3 venv:
if os.environ['CONDA_DEFAULT_ENV'] !="py35":
    print("\tPlease set the py35 { p3 | Python 3.5 } environment!
"
)
    exit()

# See also:
# Python: Determine if running inside virtualenv
# http://stackoverflow.com/questions/1871549/python-determine-if-running-inside-virtualenv  
# [ ... SNIP! ... ]

运行你的脚本(例子):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
$ python  webcam_cv3_v2_fps_v2c.py  -n50
    Please set the py35 { p3 | Python 3.5 } environment!

$ thee
  [Theano in Anaconda Python 2.7 venv (source activate theano-env)]

(theano-env) $ python  webcam_cv3_v2_fps_v2c.py  -n50
    Please set the py35 { p3 | Python 3.5 } environment!

(theano-env) $ tf
  [TensorFlow in Anaconda Python 2.7 venv (source activate tf-env]

(tf-env) $ python  webcam_cv3_v2_fps_v2c.py  -n50
    Please set the py35 { p3 | Python 3.5 } environment!

(tf-env) $ p2
  [Anaconda Python 2.7 venv (source activate py27)]

(py27) $ python  webcam_cv3_v2_fps_v2c.py  -n50
    Please set the py35 { p3 | Python 3.5 } environment!

(py27) $ p3
  [Anaconda Python 3.5 venv (source activate py35)]

(py35) $ python  webcam_cv3_v2_fps_v2c.py  -n50

    current env: py35
    processing (live): found 2 faces and 4 eyes in this frame

    threaded OpenCV implementation
    num_frames: 50
    webcam -- approx. FPS: 18.59
    Found 2 faces and 4 eyes!

(py35) $ sd
  [Anaconda venv deactivate (source deactivate)]

$ python  webcam_cv3_v2_fps_v2c.py  -n50
    Please set the py35 { p3 | Python 3.5 } environment!

$ ## Q.E.D.  ;-)

更新:在bash脚本中使用:

您还可以在bash脚本中使用此方法(例如,必须在特定虚拟环境中运行的脚本)。示例(添加到bash脚本):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# ----------------------------------------------------------------------------
# Excerpt from: /mnt/Vancouver/Programming/scripts/tf_tb_del.sh      ## tf_tb_del: tf_tensorboard_delete
# [bash script run on command-line: calls TensorFlow-related commands, therefore must be run in tf-env venv]

if [ $CONDA_DEFAULT_ENV ]        ## << note the spaces (important in bash)!
then
    printf  '
\tvenv: tf-env
'

else
    printf '

\t*******************************************************************
'

    printf '\t***  NOTE! Must run this script in tf-env virtual environment!  ***
'

    printf '\t*******************************************************************'
    exit
fi
## [ ... snip ... ]


最简单的方法就是运行:which python,如果你在virtualenv中它会指向它的python而不是全局的python


(编辑)我发现了这种方式,你怎么看待它? (它还返回venv基本路径,甚至可用于检查env变量的readthedocs):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import os
import sys
from distutils.sysconfig import get_config_vars


def get_venv_basedir():
   """Returns the base directory of the virtualenv, useful to read configuration and plugins"""

    exec_prefix = get_config_vars()['exec_prefix']

    if hasattr(sys, 'real_prefix') is False or exec_prefix.startswith(sys.real_prefix):
        raise EnvironmentError('You must be in a virtual environment')

    return os.path.abspath(get_config_vars()['exec_prefix'] + '/../')

这里已经发布了许多很棒的方法,但只需添加一个:

1
2
import site
site.getsitepackages()

告诉你pip安装包的位置。


这是一个老问题,但上面有太多例子过于复杂。

保持简单:(在Windows 10上的Jupyter Notebook或Python 3.7.1终端)

1
2
3
4
5
6
7
8
9
import sys
print(sys.executable)```

# example output: >> `C:\Anaconda3\envs\quantecon\python.exe`

OR
```sys.base_prefix```

# Example output: >> 'C:\\Anaconda3\\envs\\quantecon'


潜在的解决方案是:

1
os.access(sys.executable, os.W_OK)

在我的情况下,我真的只想检测我是否可以按原样安装pip项目。虽然它可能不是适用于所有情况的正确解决方案,但请考虑简单地检查您是否具有Python可执行文件位置的写权限。

注意:这适用于所有版本的Python,但如果使用sudo运行系统Python,也会返回True。这是一个潜在的用例:

1
2
3
4
5
6
import os, sys
can_install_pip_packages = os.access(sys.executable, os.W_OK)

if can_install_pip_packages:
    import pip
    pip.main(['install', 'mypackage'])

在Windows操作系统中,您会看到以下内容:

1
2
C:\Users\yourusername\virtualEnvName\Scripts>activate
(virtualEnvName) C:\Users\yourusername\virtualEnvName\Scripts>

括号表示您实际上处于名为"virtualEnvName"的虚拟环境中。


它不是防弹的,但对于UNIX环境来说,简单的测试就像

1
2
if run("which python3").find("venv") == -1:
    # something when not executed from venv

对我很有用。它比测试某些属性的现有更简单,无论如何,你应该命名你的venv目录venv