TechDecember 29, 20254 min read

Python Virtual Environments Explained (venv, pip, and requirements.txt)

Understand Python virtual environments finally — why they exist, how venv works, and how requirements.txt makes projects portable.

Galvan

Galvan

Founder & Creator

Introduction

Sooner or later it happens: Project A needs requests 2.28, Project B needs 2.31, and pip happily breaks one while installing the other. Virtual environments are the fix — and the concept is simpler than the jargon suggests: each project gets its own private Python and its own private packages.

This guide explains what actually happens when you run those magic commands, so venvs stop being a ritual and start being a tool.

The Problem: One Global Python

By default, pip install puts packages into your system-wide Python. Every project shares that one pile of packages. Consequences:

  • Version conflicts between projects (the A/B problem above).
  • Uninstalling a project leaves its packages behind, forever accumulating.
  • "Works on my machine" — because your machine's global pile is unique.
  • A virtual environment is just a folder containing its own Python and its own `site-packages`. Activating it makes your terminal use that folder's Python. Nothing more mysterious than that.

    Step 1: Create and Activate

    code
    cd my-project
    python -m venv .venv
    
    # Activate:
    source .venv/bin/activate        # macOS / Linux
    .venv\Scripts\activate           # Windows

    Your prompt now shows (.venv). Proof it worked:

    code
    which python        # macOS/Linux — points inside .venv
    where python        # Windows
    pip install streamlit

    The Streamlit you just installed went into .venv/lib/.../site-packages — invisible to every other project on your machine.

    Step 2: requirements.txt — Your Project's Recipe

    code
    pip freeze > requirements.txt

    This writes every installed package *with exact versions* (streamlit==1.41.1). Anyone — future you, a teammate, a deployment server — recreates the identical environment with:

    code
    python -m venv .venv
    source .venv/bin/activate
    pip install -r requirements.txt

    This two-file pair (code + requirements.txt) is what makes a project portable. It's also what deployment platforms ask for — the Streamlit deployment guide depends entirely on this file.

    Step 3: The Habits That Matter

  • One venv per project — never share, never activate globally.
  • Name it `.venv` — the dot hides it, the name is tooling convention.
  • Never commit `.venv` — add it to .gitignore (see the Git guide); it's thousands of files of machine-specific binaries. requirements.txt *is* the portable form.
  • Install with the venv active — pip outside a venv pollutes your system Python.
  • Freeze after adding packages — new import working locally but missing on deploy is 90% a forgotten pip freeze.
  • Step 4: Everyday Management

    code
    deactivate                          # leave the venv
    pip list                            # what's installed here
    pip show streamlit                  # version + location of one package
    pip install --upgrade streamlit     # update one package
    pip uninstall requests              # remove one

    Removing a venv is just deleting the folder — it's self-contained by design. Recreating it is two commands plus one install, which is why venvs are disposable: don't clean them, replace them.

    Common Errors & Fixes

  • "pip installed it but Python can't import it" — your venv isn't active, or your editor is using the system interpreter. Check which python and set your editor's interpreter to .venv/bin/python.
  • `activate` script blocked on Windows — PowerShell's execution policy; run Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser once.
  • `ModuleNotFoundError` in a running script but fine in the terminal — two different Pythons; your IDE launched the script with the global interpreter.
  • requirements.txt has everything on my machine — you froze from the global Python; activate the project venv *first*, then freeze.
  • Key Concepts

  • Isolation — private interpreter + private site-packages per project.
  • Activation — a terminal-level PATH switch, not an installation.
  • `pip freeze` — the exact recipe for reproduction.
  • Disposable by design — delete and recreate beats debugging environments.
  • What to Try Next

  • Convert an existing project: create .venv, install its imports, freeze the requirements.
  • Try uv or poetry — faster, fancier front-ends over the same concept.
  • Deploy a venv-based project to the cloud — the Streamlit deployment walkthrough uses exactly this recipe.
  • Add .venv/ to a global gitignore so you never think about it again.
  • FAQ

    Do I really need a venv for a tiny script?

    Strictly no, practically yes — it costs ten seconds and builds the habit that saves you on the day packages conflict. Scripts that grow into projects never announce themselves in advance.

    Where did the name 'venv' come from?

    It's the standard-library module (python -m venv) since Python 3.3. Before that, virtualenv was a third-party package doing the same job — the name stuck as the generic term.

    Can two projects share one venv?

    Technically yes; practically never. The moment they need different versions of anything, you're back to the original problem — with extra confusion about which venv you're in.