There are multiple good answers here, and some less robust ones. Here's an overview.
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 variableBoth 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
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
If you're using Anaconda virtual environments, check Victoria Stuart's answer.