374

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

4

15 回答 15

278

最可靠的检查方法是检查是否sys.prefix == sys.base_prefix. 如果它们相等,则您不在虚拟环境中;如果他们不平等,你就是。在虚拟环境中,sys.prefix指向虚拟环境,并且sys.base_prefix是创建 virtualenv 的系统 Python 的前缀。

以上始终适用于 Python 3 stdlibvenv和最新virtualenv版本(自版本 20 起)。在 Python 3.3 及更早的版本中,virtualenv使用过的旧版本sys.real_prefix代替sys.base_prefix(并且sys.real_prefix不存在于虚拟环境之外),并且sys.base_prefix从未存在过。因此,处理所有这些情况的完全可靠的检查可能如下所示:

import sys

def get_base_prefix_compat():
    """Get base/real prefix, or sys.prefix if there is none."""
    return getattr(sys, "base_prefix", None) or getattr(sys, "real_prefix", None) or sys.prefix

def in_virtualenv():
    return get_base_prefix_compat() != sys.prefix

如果您只关心支持的 Python 版本和最新版本virtualenv,您可以get_base_prefix_compat()简单地替换为sys.base_prefix.

使用VIRTUAL_ENV环境变量是不可靠的。它由 virtualenv activateshell 脚本设置,但可以通过直接从 virtualenv 的bin/(或Scripts)目录运行可执行文件来使用 virtualenv 而无需激活,在这种情况下$VIRTUAL_ENV不会设置。或者,可以在 shell 中激活 virtualenv 时直接执行 non-virtualenv Python 二进制文件,在这种情况下,$VIRTUAL_ENV可以在实际未在该 virtualenv 中运行的 Python 进程中设置。

于 2009-12-10T19:07:58.100 回答
183

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

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

于 2016-08-14T04:12:16.650 回答
89

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

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 的相等性。

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

if is_venv():
    print('inside virtualenv or venv')
else:
    print('outside virtualenv or venv')

以及以下调用:

$ 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 
于 2017-03-03T13:26:36.640 回答
74

检查$VIRTUAL_ENV环境变量。

$VIRTUAL_ENV处于活动虚拟环境中时,环境变量包含虚拟环境的目录。

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

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

>>> 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 中完成。

于 2015-02-07T22:17:31.933 回答
36

这里有多个好的答案,还有一些不太可靠的答案。这是一个概述。

怎么不做

不要依赖 Python 的位置或site-packages文件夹。

如果这些设置为非标准位置,这并不意味着您实际上处于虚拟环境中。用户可以安装多个 Python 版本,而这些版本并不总是您所期望的。

避免看:

  • sys.executable
  • sys.prefix
  • pip -V
  • which python

venv此外,不要检查是否存在.venvenvs在任何这些路径中。对于具有更独特位置的环境,这将中断。例如, Pipenv使用哈希值作为其环境的名称。

VIRTUAL_ENV环境变量

两者virtualenv并在激活环境时venv设置环境变量。$VIRTUAL_ENV参见PEP 405

您可以在 shell 脚本中读出此变量,或使用此 Python 代码确定它是否已设置。

import os
running_in_virtualenv = "VIRTUAL_ENV" in os.environ

# alternative ways to write this, also supporting the case where
# the variable is set but contains an empty string to indicate
# 'not in a virtual environment':
running_in_virtualenv = bool(os.environ.get("VIRTUAL_ENV"))
running_in_virtualenv = bool(os.getenv("VIRTUAL_ENV"))

问题是,这仅在shell 脚本激活环境时才有效。activate

您可以在不激活环境的情况下启动环境的脚本,所以如果这是一个问题,您必须使用不同的方法。

sys.base_prefix

virtualenv,venvpyvenv指向sys.prefix安装在 virtualenv 中的 Python,如您所料。

同时, 的原始sys.prefix也可作为sys.base_prefix.

我们可以使用它来检测我们是否在 virtualenv 中。

import sys
# note: Python versions before 3.3 don't have sys.base_prefix
# if you're not in virtual environment
running_in_virtualenv = sys.prefix != sys.base_prefix

倒退:sys.real_prefix

现在注意,virtualenv在版本 20 之前没有设置sys.base_prefix,而是设置sys.real_prefix了。

所以为了安全起见,请按照hroncok 的回答中的建议检查两者:

import sys

real_prefix = getattr(sys, "real_prefix", None)
base_prefix = getattr(sys, "base_prefix", sys.prefix)

running_in_virtualenv = (base_prefix or real_prefix) != sys.prefix

蟒蛇

如果您使用的是 Anaconda 虚拟环境,请查看 Victoria Stuart 的回答

于 2019-09-20T10:51:19.540 回答
27

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

sys.real_prefix我的 virtualenv 中不存在并且与sys.base_prefix.

于 2012-05-24T18:15:59.747 回答
13

要检查您是否在 Virtualenv 中:

import os

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

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

import sys
import os

print(f'Python Executable: {sys.executable}')
print(f'Python Version: {sys.version}')
print(f'Virtualenv: {os.getenv("VIRTUAL_ENV")}')
于 2018-07-09T12:04:30.537 回答
9

你可以which python看看它是否指向虚拟环境中的那个。

于 2018-07-18T19:47:34.200 回答
7
  • 2019 年 11 月更新(附加)。

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

添加到 Python 脚本(代码片段):

# ----------------------------------------------------------------------------
# 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!\n")
   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!\n")
    exit()

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

例子:

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

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

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

(py35) $ python  webcam.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) $

更新 1——在 bash 脚本中使用:

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

if [ $CONDA_DEFAULT_ENV ]        ## << note the spaces (important in BASH)!
    then
        printf 'venv: operating in tf-env, proceed ...'
    else
        printf 'Note: must run this script in tf-env venv'
        exit
fi

更新 2 [2019 年 11 月]

自从我的原始帖子以来,我已经从 Anaconda venv 继续前进(并且 Python 本身已经发展了 viz -a- viz虚拟环境)。

重新检查这个问题,这里有一些更新的 Python 代码,您可以插入这些代码来测试您是否在特定的 Python 虚拟环境 (venv) 中运行。

import os, re
try:
    if re.search('py37', os.environ['VIRTUAL_ENV']):
        pass
except KeyError:
    print("\n\tPlease set the Python3 venv [alias: p3]!\n")
    exit()

这是一些解释性代码。

[victoria@victoria ~]$ date; python --version
  Thu 14 Nov 2019 11:27:02 AM PST
  Python 3.8.0

[victoria@victoria ~]$ python
  Python 3.8.0 (default, Oct 23 2019, 18:51:26) 
  [GCC 9.2.0] on linux
  Type "help", "copyright", "credits" or "license" for more information.

>>> import os, re

>>> re.search('py37', os.environ['VIRTUAL_ENV'])
<re.Match object; span=(20, 24), match='py37'>

>>> try:
...     if re.search('py37', os.environ['VIRTUAL_ENV']):
...       print('\n\tOperating in Python3 venv, please proceed!  :-)')
... except KeyError:
...     print("\n\tPlease set the Python3 venv [alias: p3]!\n")
... 

    Please set the Python3 venv [alias: p3]!

>>> [Ctrl-d]
  now exiting EditableBufferInteractiveConsole...

[victoria@victoria ~]$ p3
  [Python 3.7 venv (source activate py37)]

(py37) [victoria@victoria ~]$ python --version
  Python 3.8.0

(py37) [victoria@victoria ~]$ env | grep -i virtual
  VIRTUAL_ENV=/home/victoria/venv/py37

(py37) [victoria@victoria ~]$ python
  Python 3.8.0 (default, Oct 23 2019, 18:51:26) 
  [GCC 9.2.0] on linux
  Type "help", "copyright", "credits" or "license" for more information.

>>> import os, re
>>> try:
...     if re.search('py37', os.environ['VIRTUAL_ENV']):
...       print('\n\tOperating in Python3 venv, please proceed!  :-)')
... except KeyError:
...     print("\n\tPlease set the Python3 venv [alias: p3]!\n")
... 

    Operating in Python3 venv, please proceed!  :-)
>>> 
于 2016-10-18T03:35:08.557 回答
4

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

于 2019-07-19T09:11:54.893 回答
1

(编辑)我是这样发现的,你怎么看?(它还返回 venv 基本路径,甚至适用于不检查env变量的 readthedocs)

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'] + '/../')
于 2017-07-16T07:26:30.483 回答
0

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

import site
site.getsitepackages()

告诉您pip安装软件包的位置。

于 2019-08-12T07:33:35.830 回答
-1

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

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

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

于 2016-10-18T13:40:57.123 回答
-1

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

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

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

于 2017-07-07T14:58:15.350 回答
-1

一个潜在的解决方案是:

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

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

注意:这适用于所有版本的 Python,但True如果您使用sudo. 这是一个潜在的用例:

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'])
于 2018-05-02T15:43:02.367 回答