Skip to the solution
EasyDSA13 min read

Why use virtual environments?

1.1k views

The problem

Question presented to candidate: "Why do Python developers create a virtual environment for each project? What problem does it solve, what is actually inside one, and how does Python know it is running in one?"

What a strong answer should cover:

  • Without isolation, every project shares one site-packages, so only one version of each library can be installed; two projects needing different versions conflict, and installing into the system Python can break OS tools
  • A virtual environment is a folder with its own site-packages, a python link (or copy) to a base interpreter, and a pyvenv.cfg; it shares the base interpreter and standard library, it is not a copy of Python
  • Python detects it at start-up from pyvenv.cfg next to or one level above the executable, and sets sys.prefix to the venv while sys.base_prefix stays at the base install; sys.prefix != sys.base_prefix means "in a venv"
  • Activation only changes PATH (and VIRTUAL_ENV, the prompt); running the venv's python directly works without activating
  • Reproducibility comes from pinning what goes into the venv (requirements.txt, a lockfile such as uv.lock); the venv itself is disposable and should not be committed
  • PEP 668 "externally managed" system Pythons (Debian 12, Ubuntu 23.04+) now refuse pip install outside a venv; python -m venv (PEP 405, Python 3.3) or uv venv are the standard tools

Code / implementation expected: Optional β€” the python -m venv .venv / activate / install workflow, or checking sys.prefix against sys.base_prefix.

  • venv
  • pip

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

13 min read Β· 12 sections

Run the code

Edit the code and run it here. Each console line with an expected value becomes a test.

PythonTwo projects, two versions: one shared folder vs one folder each
PythonCreate a real venv and compare it with the base interpreter
# A real virtual environment, created and inspected from Python.
# Needs a real interpreter and subprocess, so it does not run in the browser.
import os
import subprocess
import sys
import tempfile
import venv

work = tempfile.mkdtemp()
env_dir = os.path.join(work, ".venv")
venv.EnvBuilder(with_pip=False).create(env_dir)    # same as: python -m venv --without-pip .venv

bindir = "Scripts" if os.name == "nt" else "bin"
env_python = os.path.join(env_dir, bindir, "python")

print("files in the venv root:", sorted(os.listdir(env_dir)))
with open(os.path.join(env_dir, "pyvenv.cfg")) as f:
    keys = [line.split("=")[0].strip() for line in f if "=" in line]
print("pyvenv.cfg keys:", sorted(keys))

PROBE = r'''
import sys, sysconfig, os
print("in venv:", sys.prefix != sys.base_prefix)
print("prefix is the venv folder:", os.path.basename(sys.prefix))
print("base_prefix is the base install:", sys.base_prefix == BASE)
site = sysconfig.get_paths()["purelib"]
print("site-packages:", os.path.relpath(site, sys.prefix).replace(os.sep, "/"))
try:
    import hello_pkg
    print("hello_pkg:", hello_pkg.MSG)
except ImportError:
    print("hello_pkg: not installed here")
'''

def run(python):
    code = "BASE = " + repr(sys.base_prefix) + "\n" + PROBE
    out = subprocess.run([python, "-c", code], capture_output=True, text=True, check=True)
    return out.stdout

# "Install" a package into the venv only: drop a module into its site-packages.
site = subprocess.run([env_python, "-c", "import sysconfig; print(sysconfig.get_paths()['purelib'])"],
                      capture_output=True, text=True, check=True).stdout.strip()
with open(os.path.join(site, "hello_pkg.py"), "w") as f:
    f.write('MSG = "imported from the venv"\n')

print("--- venv python ---")
print(run(env_python), end="")
print("--- base python ---")
print(run(sys.executable), end="")

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 5 of 139 in Python

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Python questions
Up nextEasy

How does slicing with start:stop:step work?

Continue