是否可以确定当前脚本是否在 virtualenv 环境中运行?
15 回答
最可靠的检查方法是检查是否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 activate
shell 脚本设置,但可以通过直接从 virtualenv 的bin/
(或Scripts
)目录运行可执行文件来使用 virtualenv 而无需激活,在这种情况下$VIRTUAL_ENV
不会设置。或者,可以在 shell 中激活 virtualenv 时直接执行 non-virtualenv Python 二进制文件,在这种情况下,$VIRTUAL_ENV
可以在实际未在该 virtualenv 中运行的 Python 进程中设置。
尝试使用pip -V
(注意大写 V)
如果您正在运行虚拟环境。它将显示环境位置的路径。
这是对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_prefix
与sys.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
检查$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 中完成。
这里有多个好的答案,还有一些不太可靠的答案。这是一个概述。
怎么不做
不要依赖 Python 的位置或site-packages
文件夹。
如果这些设置为非标准位置,这并不意味着您实际上处于虚拟环境中。用户可以安装多个 Python 版本,而这些版本并不总是您所期望的。
避免看:
sys.executable
sys.prefix
pip -V
which python
venv
此外,不要检查是否存在.venv
或envs
在任何这些路径中。对于具有更独特位置的环境,这将中断。例如,
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
,venv
并pyvenv
指向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 的回答。
根据http://www.python.org/dev/peps/pep-0405/#specification上的 virtualenv pep,您可以sys.prefix
改为使用os.environ['VIRTUAL_ENV']
。
在sys.real_prefix
我的 virtualenv 中不存在并且与sys.base_prefix
.
要检查您是否在 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")}')
你可以which python
看看它是否指向虚拟环境中的那个。
- 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 月]
- 为简单起见,我喜欢马特的回答(https://stackoverflow.com/a/51245168/1904943)。
自从我的原始帖子以来,我已经从 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! :-)
>>>
最简单的方法是运行:which python
,如果你在一个 virtualenv 中,它将指向它的 python 而不是全局的
(编辑)我是这样发现的,你怎么看?(它还返回 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'] + '/../')
这里已经发布了很多很棒的方法,但只是添加了一个:
import site
site.getsitepackages()
告诉您pip
安装软件包的位置。
它不是防弹的,但对于 UNIX 环境来说,简单的测试就像
if run("which python3").find("venv") == -1:
# something when not executed from venv
对我很有用。它比测试某些属性的存在更简单,无论如何,你应该命名你的 venv directory venv
。
在 Windows 操作系统中,您会看到如下内容:
C:\Users\yourusername\virtualEnvName\Scripts>activate
(virtualEnvName) C:\Users\yourusername\virtualEnvName\Scripts>
括号表示您实际上处于名为“virtualEnvName”的虚拟环境中。
一个潜在的解决方案是:
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'])