Skip to content

Virtual Environments & pip

Every Python project should run inside its own virtual environment. Without one, every pip install lands in the global Python installation, where packages from different projects collide and version conflicts accumulate silently. A virtual environment is a self-contained directory tree with its own Python interpreter and site-packages, completely isolated from the system Python and from every other project.

Python ships with the venv module in its standard library. The convention is to name the environment .venv and place it at the project root.

Terminal window
# create a virtual environment in .venv/
python -m venv .venv

After creation the environment is inert. Activation prepends .venv/bin (or .venv\Scripts on Windows) to your PATH so that python and pip resolve to the isolated copies.

Terminal window
# activate — macOS / Linux
source .venv/bin/activate
# activate — Windows (PowerShell)
.venv\Scripts\Activate.ps1
# you should now see (.venv) in your prompt

With the environment active, pip installs into .venv/lib/ rather than the global site-packages.

Terminal window
# install a single package
pip install requests
# install a specific version
pip install "requests==2.31.0"
# install from requirements.txt
pip install -r requirements.txt

pip freeze prints every installed package and its exact version. Redirect the output to requirements.txt so collaborators and CI can reproduce the exact environment.

Terminal window
# write all installed packages + versions to requirements.txt
pip freeze > requirements.txt
# example output in requirements.txt:
# certifi==2024.2.2
# charset-normalizer==3.3.2
# idna==3.7
# requests==2.31.0
# urllib3==2.2.1

When you are done working on a project, deactivate restores your original PATH.

Terminal window
deactivate

A conventional Python project keeps the virtual environment at the root alongside source, tests, and dependency files.

flowchart TD
  root["project root"] --> venv[".venv/ (never commit — add to .gitignore)"]
  root --> src["src/"]
  src --> myapp["myapp/"]
  root --> tests["tests/"]
  root --> reqs["requirements.txt"]
  root --> pyproj["pyproject.toml"]
Typical Python project layout
What command creates a virtual environment named .venv?
What does `pip freeze > requirements.txt` do?
Why should .venv/ be listed in .gitignore?