DEV Community

Cover image for Python venv explained: stop breaking dependencies
Tlaloc-Es
Tlaloc-Es

Posted on

Python venv explained: stop breaking dependencies

Python venv is the standard way to isolate dependencies per project.
Without it, pip install mutates one shared interpreter until versions collide.

If you have ever seen an import break after “just installing one package” for another repo, this is the mechanism behind it.

We will walk through what venv actually creates (paths, pyvenv.cfg, and interpreter prefixes) and why that isolation makes dependency state reproducible.

The problem: one Python for every project

Without isolation, all packages are installed into your system-wide Python:

pip install requests
Enter fullscreen mode Exit fullscreen mode

Looks harmless, but it breaks at scale:

  • Project A needs requests 2.28
  • Project B needs requests 2.32
  • Project C needs a urllib3 version that conflicts with A

Result: version conflicts, hard-to-reproduce bugs, and the classic “it works on my machine.”

That is why Python virtual environments exist: to isolate dependencies per project.

Before venv: no official contract

Before Python 3.3, the most used tool was virtualenv. It worked, but it was not part of the language standard.

Different tools handled isolation differently, which hurt interoperability.

The ecosystem needed an official baseline.

PEP 405: the turning point for Python environments

In 2012, PEP 405 defined how virtual environments should work in Python.

The idea is elegant: each environment has its own root, its own package path, and a config file that tells the interpreter “you are in an isolated environment.”

That file is:

  • pyvenv.cfg

With that, Python knows when to use environment packages and when to use the base interpreter.

Creating an environment with python venv (the right way)

python -m venv .venv
Enter fullscreen mode Exit fullscreen mode

Useful variants:

# Pick a specific Python version
python3.12 -m venv .venv

# Windows alternative
py -3.12 -m venv .venv

# Create environment without pip
python -m venv .venv --without-pip

# Recreate from scratch if it already exists
python -m venv .venv --clear
Enter fullscreen mode Exit fullscreen mode

The .venv naming convention is a good practice because many tools and templates already recognize it.

What happens under the hood when you create .venv

When you run python -m venv, Python performs four main steps:

  1. Creates the environment folder structure.
  2. Generates pyvenv.cfg with base interpreter metadata.
  3. Sets up the Python executable inside the environment.
  4. Installs pip (unless you disable it).

In short: it is not magic, it is a controlled structure for reproducible dependency management.

How to check if you are inside a virtual environment

This is the most reliable check:

import sys

in_venv = sys.prefix != sys.base_prefix
print("Inside venv:", in_venv)
print("prefix:", sys.prefix)
print("base_prefix:", sys.base_prefix)
Enter fullscreen mode Exit fullscreen mode

If sys.prefix and sys.base_prefix are different, you are inside a virtual environment.

Activate or not activate?

Activating an environment changes your shell PATH so python and pip point to .venv.

But technically, activation is optional if you call the executable directly:

# Without activation
.venv/bin/python script.py

# On Windows
.venv\Scripts\python.exe script.py
Enter fullscreen mode Exit fullscreen mode

For CI/CD scripts, explicit paths are often more robust.

A common pip mistake to avoid

Using pip directly can target the wrong interpreter.

Better pattern:

python -m pip install fastapi
Enter fullscreen mode Exit fullscreen mode

This guarantees pip installs into the same interpreter you are running.

Common mistakes

  • Activating .venv, but your IDE/terminal still runs the global python (check which python / where python).
  • Creating the environment with one Python version, then upgrading Python and reusing the same .venv (recreate it).
  • Enabling --system-site-packages and accidentally importing global packages, making bugs non-reproducible.
  • Reusing one .venv across branches with different dependencies and assuming it will stay consistent.

Maintenance pro tip (without changing your workflow)

Once you start creating many Python environments for quick tests, you end up with forgotten environments.

The real problem is figuring out which ones are stale once you have dozens of repos. KillPy can scan and list old environments so you can review and remove them deliberately.

Conclusion

If you understand this, you are already ahead of most developers:

  • Python venv is not just a terminal trick; it is real isolation
  • Python virtual environments prevent project conflicts
  • good dependency management starts with separate environments

In the next part, we will open the .venv folder and inspect its full anatomy: bin/Scripts, site-packages, dist-info, and what each piece means.


Has pip ever installed packages into the wrong environment for you? Share your story in the comments and pass this article to someone starting with Python.

Top comments (0)