Determine If Python Is Running Inside Virtualenv

Determine if Python is running inside virtualenv

The most reliable way to check for this is to check whether sys.prefix == sys.base_prefix. If they are equal, you are not in a virtual environment; if they are unequal, you are. Inside a virtual environment, sys.prefix points to the virtual environment, and sys.base_prefix is the prefix of the system Python the virtualenv was created from.

The above always works for Python 3 stdlib venv and for recent virtualenv (since version 20). Older versions of virtualenv used sys.real_prefix instead of sys.base_prefix (and sys.real_prefix did not exist outside a virtual environment), and in Python 3.3 and earlier sys.base_prefix did not ever exist. So a fully robust check that handles all of these 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 get_base_prefix_compat() != sys.prefix

If you only care about supported Python versions and latest virtualenv, you can replace get_base_prefix_compat() with simply sys.base_prefix.

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.

how can I find out which python virtual environment I am using?

You can use sys.prefix to determine which virtualenv you're in.

import sys
print(sys.prefix)

from the sys docs

A string giving the site-specific directory prefix where the platform independent Python files are installed

How to test if Python is running from a virtualenv during package installation

Ultimately it seems that your question is really about how to detect whether the running Python is in a virtualenv. To get to the bottom of this we must understand how virtualenv actually works.

When you run the activate script inside a virtualenv, it does two things:

  • it updates the PATH environment variable to include the bin directory from the virtualenv, so that when you run python the binary from the virtualenv will run.
  • it sets a variable VIRTUAL_ENV so that the activate script itself can keep track of the activation.

It's perfectly acceptable to directly run the python from the virtualenv, and at runtime python does not use the VIRTUAL_ENV variable at all. Instead, it determines the directory containing the running pythonbinary and uses the parent directory as its "prefix".

You can determine the system's prefix by importing the sys module and consulting sys.prefix. However, it would be a bad idea to depend on the value of this when a virtualenv is not activated because this is a build-time setting for Python that can easily be customized, and it will definitely vary between platforms.

However, Python does have one slight runtime difference when it runs from a virtualenv prefix vs. its compiled-in prefix: the sys package has an additional variable real_prefix that returns the prefix that is compiled into the Python binary. Therefore one could use this to recognize that Python is running in a non-default location, which is reasonably likely to mean it's running from a virtualenv:

import sys

if getattr(sys, "real_prefix", None) is not None:
print "Maybe in a virtualenv"
else:
print "Probably not in a virtualenv"

However, even this is not an exact science. All this really tells you is that the python binary is not at the location specified at compile time. It does not tell you whether the current user has access to write to /usr/share/man -- there are some (possibly edge) cases where this won't give you the right answer:

  • If the user has compiled his own Python from source in his home directory and its compiled prefix is /home/johnd/local-python then real_prefix won't be set but the user still has write access to his Python lib directory, and probably not write access to /etc or /usr/share/man

  • Likewise, on some systems the administrator may have granted group-write privileges on /usr/lib/python2.7 to a certain group of app developers so that they can install Python modules, but not have granted them write access to other system files.

So I think in the end the best you can do is a heuristic and it may be better to instead just avoid using absolute paths in data_files for any module you expect to be used inside a virtualenv. A compromise might be to simply split your module into two distributions, one representing the localizable source files and another representing the system-wide configuration to make it run. The latter can depend on the former so that users can still easily install it, but those using virtualenv have the option of using the other former directly.

How can a shell function know if it is running within a virtualenv?

Actually, I just found a similar question, from which one can easily derive an answer to this one:

Python: Determine if running inside virtualenv

E.g., a shell script can use something like

python -c 'import sys; print (sys.real_prefix)' 2>/dev/null && INVENV=1 || INVENV=0

(Thanks to Christian Long for showing how to make this solution work with Python 3 also.)

EDIT: Here's a more direct (hence clearer and cleaner) solution (taking a cue from JuanPablo's comment):

INVENV=$(python -c 'import sys; print ("1" if hasattr(sys, "real_prefix") else "0")')

Python: How do you check what is in virtualenv?

Once you activate your virtual environment, you should be able to list out packages using pip list and verify version using python --version.

Python script inside virtual env not running in command line

If you want to directly run a script in a virtual env, edit the shebang line to include the Python interpreter from that env:

#!/path/to/env/bin/python3

That interpreter will find the pyvenv.cfg file at its parent directory and will adjust all paths accordingly. That is an equivalent of activating the environmnet.


The process can be automated. Create a package with a setup.py and declare which files are scripts. When the package is installed, the scripts will installed in the <venv>/bin subdirectory with correct shebang lines.

You may want to create a symlink from /usr/bin to have the script in the path.

Activate virtualenv from a system running a different python version

A virtualenv doesn't have a full Python installation. Instead, it links to an installation present on the system (FYI that link is in <env>/lib/orig-prefix.txt). The env's directory tree has some stubs and special logic but it uses the bulk from that installation.

So if you run activate on a system that doesn't have the same Python at the same path as the one virtualenv was created for, that script won't work correctly. It might happen to hook to something else present at the same path but this is not a supported scenario so all bets are off.


If you need a "fully enclosed environment", you may want to take a look at pyenv which does exactly that -- installs a full Python under your home dir. (Or you can just install Python from source to somewhere under your home dir -- but pyenv makes it easy to switch to that installation and back.)



Related Topics



Leave a reply



Submit