Virtual environments: prefix and base_prefix

sys · Advanced · 8 min

'It works on my machine' bugs often come from the wrong interpreter or environment being active.

A virtual environment is a directory with its own site-packages and a pyvenv.cfg file pointing at a base Python installation. sys describes the relationship:

  • sys.prefix is the active environment's root directory.
  • sys.base_prefix is the installation the environment was created from.
  • Inside a venv they differ; outside one they are equal. So sys.prefix != sys.base_prefix is the standard check.

sys.executable points into the venv's bin/ (or Scripts\ on Windows), even though it is usually a symlink to the base binary. That's how Python finds pyvenv.cfg at startup and sets the prefixes accordingly; no shell activation is required. Running .venv/bin/python script.py directly uses the environment just as well as activating it first.

Diagnosing environment mix-ups:

  • python -c "import sys; print(sys.executable)" shows which interpreter a command resolves to.
  • python -m pip ... guarantees pip installs into that same interpreter, unlike a bare pip that may belong to another one.
  • python -m site prints sys.path and the user site directory.

Activation only puts the venv's bin first on PATH and sets VIRTUAL_ENV; the environment variable alone does not make Python use the venv.

Example

import subprocess
import sys
import venv

def in_venv():
    return sys.prefix != sys.base_prefix

venv.create("env", with_pip=False)
py = "env/Scripts/python.exe" if sys.platform == "win32" else "env/bin/python"
check = "import sys; print(sys.prefix != sys.base_prefix, sys.prefix.endswith('env'))"
out = subprocess.run([py, "-c", check], capture_output=True, text=True)
print(out.stdout.strip())     # True True
print(isinstance(in_venv(), bool))   # True

Remember

  • sys.prefix != sys.base_prefix means a virtual environment is active
  • Running the venv's python binary directly is enough; activation only edits PATH
  • Use python -m pip so packages go into the interpreter you actually run

Watch out for

  • Running a bare pip install that belongs to a different Python than the one executing the code.

Check yourself

  1. You run /proj/.venv/bin/python app.py without activating the venv. Which packages does app.py see?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.python.org/3/library/sys.html#sys.prefix