Is it possible to determine if the current script is running inside a virtualenv environment?
The reliable and documented way is to compare sys.prefix
and sys.base_prefix
. If they're equal, you're not in a virtual environment, otherwise you are. Inside a venv, sys.prefix
points to the directory of the virtual environment, and sys.base_prefix
to the Python interpreter used to create the environment.
This is documented under How venvs work:
It is sufficient to check
sys.prefix != sys.base_prefix
to determine if the current interpreter is running from a virtual environment.
This works for Python stdlib venv
and for virtualenv
(since version 20):
def in_venv():
return sys.prefix != sys.base_prefix
Older versions of virtualenv
used sys.real_prefix
instead of sys.base_prefix
, and sys.real_prefix
did not exist outside a virtual environment. In Python 3.3 and earlier sys.base_prefix
did not ever exist. So a check that also handles some legacy cases could look like this:
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 sys.prefix != get_base_prefix_compat()
Using the VIRTUAL_ENV
environment variable is not reliable. It is set by the virtualenv activate
shell script, but a virtualenv can be used without activation by directly running an executable from the virtualenv's bin/
(or Scripts
) directory, in which case $VIRTUAL_ENV
will not be set. Or a non-virtualenv Python binary can be executed directly while a virtualenv is activated in the shell, in which case $VIRTUAL_ENV
may be set in a Python process that is not actually running in that virtualenv.
PYTHON_ENV=$(python -c "import sys; sys.stdout.write('1') if hasattr(sys, 'real_prefix') else sys.stdout.write('0')")
–
Selah $VIRTUAL_ENV
–
Mayolamayon venv
. –
Gild venv
module and changes in latest virtualenv
. –
Cyprinid ipython
REPL since the sys.prefix
will be something like /usr/local/Cellar/ipython/8.0.1/libexec
which is never the same as the base prefix. –
Jambeau ipython3
from the command line (sans venv) in Fedora 36, sys.prefix
and sys.base_prefix
are both /usr
, and sys.executable
is /usr/bin/python3
. –
Lisandralisbeth Try using pip -V
(notice capital V)
If you are running the virtual env. it'll show the path to the env.'s location.
virtualenv
around a lot, it's possible this can fail or lie to you. If it's lying, you can do find /path/to/venv/ -type f -exec sed -ie "s:/old/path/to/venv:/path/to/venv:g" {} \+
. If it's failing (I got "bad marshal data") you'll need to wipe the .pyc files with find /path/to/venv -type f -name "*.pyc" -exec rm {} \+
(don't worry, they'll rebuild automatically). –
Toed ...\lib\site-packages
in the %PATH%
. So it will return a false positive in that case. –
Doxy pip -V
returns path of user installation of pip, if not in a venv. Therefore, this doesn't tell you if a venv is activated or not. –
Ceremonious Check the $VIRTUAL_ENV
environment variable.
The $VIRTUAL_ENV
environment variable contains the virtual environment's directory when in an active virtual environment.
>>> import os
>>> os.environ['VIRTUAL_ENV']
'/some/path/project/venv'
Once you run deactivate
/ leave the virtual environment, the $VIRTUAL_ENV
variable will be cleared/empty. Python will raise a KeyError
because the environment variable was unset.
>>> 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'
These same environment variable checks can of course also be done outside of the Python script, in the shell.
virtualenv
virtualenv and a venv
virtualenv. –
Zinck This is an improvement of the accepted answer by Carl Meyer. It works with virtualenv for Python 3 and 2 and also for the venv module in Python 3:
import sys
def is_venv():
return (hasattr(sys, 'real_prefix') or
(hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix))
The check for sys.real_prefix
covers virtualenv, the equality of non-empty sys.base_prefix
with sys.prefix
covers venv.
Consider a script that uses the function like this:
if is_venv():
print('inside virtualenv or venv')
else:
print('outside virtualenv or venv')
And the following invocation:
$ 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
def is_venv(): return hasattr(sys, 'real_prefix') or sys.base_prefix != sys.prefix
. Just sayin'. –
Dulcine pipenv
created virtual environments. –
Zygospore pipenv run
and pipenv shell
) for me (MacOS Ventura on Mac M1, Python 3.9.10) –
Wrist There are multiple good answers here, and some less robust ones. Here's an overview.
How not to do it
Do not rely on on the location of Python or the site-packages
folder.
If these are set to non-standard locations, that does not mean you're actually in a virtual environment. Users can have more than one Python version installed, and those are not always where you expect them to be.
Avoid looking at:
sys.executable
sys.prefix
pip -V
which python
Also, do not check for the presence of venv
, .venv
or envs
in any of these paths.
This will break for environments with a more unique location. For example,
Pipenv uses hash values as the name for its environments.
VIRTUAL_ENV
environment variable
Both virtualenv
and venv
set the environment variable $VIRTUAL_ENV
when activating an environment.
See PEP 405.
You can read out this variable in shell scripts, or use this Python code to determine if it's set.
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"))
The problem is, this only works when the environment is activated by the activate
shell script.
You can start the environment's scripts without activating the environment, so if that is a concern, you have to use a different method.
sys.base_prefix
virtualenv
, venv
and pyvenv
point sys.prefix
to the Python installed inside of the virtualenv as you would expect.
At the same time, the original value of sys.prefix
is also made available as sys.base_prefix
.
We can use that to detect if we're in a 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
Fallback: sys.real_prefix
Now watch out, virtualenv
before version 20 did not set sys.base_prefix
but it set sys.real_prefix
instead.
So to be safe, check both as suggested in hroncok's answer:
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
If you're using Anaconda virtual environments, check Victoria Stuart's answer.
running_in_virtualenv = sys.*base_*prefix != sys.prefix
–
Stammer if hasattr(sys, 'real_prefix'):
test, which no longer worked. –
Stammer sys.prefix
? Seems like it's possible to be effectively running in a virtual env without VIRTUAL_ENV
set, e.g. by doing /Users/me/.virtualenvs/myenv/bin/python3 script.py
. In this case, sys.prefix
or or sys.exec_prefix
seems to be the best way to discern (though I'm not sure how you would tell if it is venv-like, I guess by looking at sys.path
) –
Coons sys.prefix
by itself does not tell you if that Python is a virtualenv or not. –
Zinck prefix
could be pointing to a prefix path that isn't a virtualenv. How does one then tell if prefix
is indeed a virtualenv? I've seen counter-examples where VIRTUAL_ENV
is not set, e.g. poetry envs. –
Coons sys.prefix
to sys.base_prefix
. –
Zinck sys.prefix != sys.base_prefix
only suggests, but does not confirm, you are operating inside a virtualenv (or rather, any isolated env)? Basically, is an isolated env the only thing that can change sys.prefix
to something other than sys.base_prefix
? That seems to be what the docs suggest. But the python path system is zany, so I want to be 100% sure. Also I'm talking python>=3.3
. –
Coons According to the virtualenv pep at http://www.python.org/dev/peps/pep-0405/#specification you can just use sys.prefix
instead os.environ['VIRTUAL_ENV']
.
the sys.real_prefix
does not exist in my virtualenv and same with sys.base_prefix
.
sys.real_prefix
. –
Cyprinid env |grep VIRTUAL_ENV |wc -l
which will return a 1 if in a venv or a 0 if not. –
Baran [[ -n $VIRTUAL_ENV ]] && echo virtualenv
or [[ -z $VIRTUAL_ENV ]] && echo not virtualenv
depending on your needs. –
Vestavestal To check whether your inside Virtualenv:
import os
if os.getenv('VIRTUAL_ENV'):
print('Using Virtualenv')
else:
print('Not using Virtualenv')
You can also get more data on your environment:
import sys
import os
print(f'Python Executable: {sys.executable}')
print(f'Python Version: {sys.version}')
print(f'Virtualenv: {os.getenv("VIRTUAL_ENV")}')
- Updated Nov 2019 (appended).
I routinely use several Anaconda-installed virtual environments (venv). This code snippet/examples enables you to determine whether or not you are in a venv (or your system environment), and to also require a specific venv for your script.
Add to Python script (code snippet):
# ----------------------------------------------------------------------------
# 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
# https://mcmap.net/q/14761/-how-to-determine-if-python-is-running-inside-a-virtualenv
# [ ... SNIP! ... ]
Example:
$ 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) $
Update 1 -- use in bash scripts:
You can also use this approach in bash scripts (e.g., those that must run in a specific virtual environment). Example (added to bash script):
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
Update 2 [Nov 2019]
- For simplicity, I like Matt's answer (https://mcmap.net/q/14761/-how-to-determine-if-python-is-running-inside-a-virtualenv).
Since my original post I've moved on from Anaconda venv (and Python itself has evolved viz-a-viz virtual environments).
Reexamining this issue, here is some updated Python code that you can insert to test that you are operating in a specific Python virtual environment (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()
Here is some explanatory code.
[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! :-)
>>>
You can do which python
and see if its pointing to the one in virtual env.
which
is not available by default on Windows. You could use where
instead on Windows, or employ whichcraft. Or look at sys.executable
. But still, there are better methods. –
Zinck Easiest way is to just run: which python
, if you are in a virtualenv it will point to its python instead of the global one
You can look for the 'signature' of whatever venv method you're trying to support. In my case I want to support:
python -m venv venv_dir
or
virtualenv venv_dir
So I can write:
import sys
from pathlib import Path
IS_VENV_ENVIRONMENT = (Path(sys.prefix) / "pyvenv.cfg").exists()
See: https://docs.python.org/3/library/venv.html
"Running this command creates the target directory (creating any parent directories that don’t exist already) and places a pyvenv.cfg file in it"
NB: virtualenv also creates the same file but I couldn't see any docs about that, I only noticed by experiment.
(edited) I found that way, what do you think of it ? (it also returns the venv base path and works even for readthedocs where checking the env variable does not):
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'] + '/../')
In windows OS you see something like this:
C:\Users\yourusername\virtualEnvName\Scripts>activate
(virtualEnvName) C:\Users\yourusername\virtualEnvName\Scripts>
Parentheses mean that you are actually in the virtual environment called "virtualEnvName".
If you want to directly check if you are in a virtualenv the above answers are the correct solutions.
However, if the real problem you are trying to solve is determining whether you can pip install
a dependency without erroring (something that would be true if you were in a virtualenv), you can simply check if you have write permissions for the location of the Python executable:
os.access(sys.executable, os.W_OK)
This works in all versions of Python, and also returns True
if you run the system Python with sudo
. Here's an example of how this would be useful:
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'])
There are a lot of great methods posted here already, but just adding one more:
import site
site.getsitepackages()
tells you where pip
installed the packages.
site.getsitepackages()
outputs a directory that's not the system one, then you can deduce you're in a virtual environment. –
Rectal virtualenv
. –
Zinck venv
you're using. –
Rectal If you are using Anaconda here is the solution. This command lists all the discoverable environments
conda info --envs
I typically use a bash wrapper script to start my application and was running into the problem of imports not working because of pip packages not being installed outside the virtual environment.
Using the solution provided by Matt Harasymczuk, here are the few lines of bash script to check the virtual environment has been activated before starting the application.
#!/bin/bash
# check the virtual environment is active
if [ -z "$VIRTUAL_ENV" ]
then
echo "[ERROR] Virtual environment not activated"
exit 1
fi
# start the application
python3 # amend with application name and other details
# end of file
As not already mentioned, and time has moved on since this question was made, I thought I'd mention pyenv-virtualenv.
pyenv allows multiple python interpreters to exist on the same system at the same time without collision. The interpreter can automatically change when you chdir into a given path. https://github.com/pyenv/pyenv
pyenv-virtualenv is a pyenv plugin that, like venv/pipenv, creates independent virtualenvs each with different module configurations, but now that env also specifies which interpreter(s) can be used. https://github.com/pyenv/pyenv-virtualenv
If you are using pyenv or pyenv-virtualenv then this one line bash command will work.
test -x $(which pyenv) && { pyenv which python | grep -q "^$(pyenv root)"; } && echo "1"
This could be used to set an environment variable that Python can read via one of the hook scripts that pyenv uses, or updated via the shell prompt hook variable, $PROMPT_COMMAND. (Note: shell hook example may need some speedup shortcuts/tricks or risk being annoying)
e.g. Here IN_VENV is either 'system' or a version number or a virtualenv
export IN_VENV=$(test -x $(which pyenv) && { pyenv which python | grep -q "^$(pyenv root)"; } && pyenv version-name)
If you need to detect this inside Python with no help from the os, then
from subprocess import run
# run cmd in shell
# return None if error else stdout or ""
def sh(cmd, **kw):
res = run(cmd, capture_output=True, shell=True, **kw)
return None if res.returncode != 0 else res.stdout.decode("ascii").strip()
pyenv = sh("which pyenv")
assert pyenv is not None, "No pyenv command"
assert sh(f"test -x {pyenv}") is not None, "pyenv is non-exe"
pycmd = sh(f"pyenv which python")
assert pycmd is not None, "no pyenv python"
root = sh(f"{pyenv} root")
assert root is not None, "'pyenv root' did not run"
in_pyenv = sh(f"grep -q ^{root}", input=pycmd.encode('utf-8') is not None
This not only finds the virtualenv but proves it is working.
It's not bullet-proof but for UNIX environments simple test like
if run("which python3").find("venv") == -1:
# something when not executed from venv
works great for me. It's simpler then testing existing of some attribute and, anyway, you should name your venv directory venv
.
© 2022 - 2024 — McMap. All rights reserved.
import sys print(sys.executable)
# example output: >>C:\Anaconda3\envs\quantecon\python.exe
ORsys.base_prefix
# Example output: >> 'C:\\Anaconda3\\envs\\quantecon' – Katmandu${VIRTUAL_ENV}
, then you will know whether python will be running in a venv or not. – Ceremoniouspip list
. Name of venv shall not matter (same for no venv), rather versions of used packages, right? – Dugout