Virtual environments¶
A virtual environment is a self-contained Python — a private
directory with its own copy of the interpreter, its own pip, and
its own site-packages. Using one per project is the difference
between dependency hygiene and dependency chaos.
Time commitment: 10-15 minutes
Prerequisites:
- Comfortable with the basics of
pip install - You can open a terminal
Learning objectives¶
By the end of this tutorial, you will be able to:
- Create, activate, and deactivate a virtual environment with
venv - Explain what activation actually does
- Adopt a per-project workflow that keeps installs isolated
!!! note "Browser note" The commands below run in your terminal, not in this page's browser kernel. Pyodide doesn't expose a shell, so the bash blocks here are for reference — copy them into a real terminal to follow along.
Why isolation matters¶
Without virtual environments, every pip install adds to a single
shared site-packages directory. Two projects that both depend on
requests are fine; two projects that need different versions of
requests are not. And pip install for the system Python on Linux
or macOS is a recipe for breaking system tools that depend on
specific package versions.
A virtual environment gives each project its own sealed bubble. Installs go into that bubble; the system Python is untouched.
Creating a venv¶
Python 3 ships with the venv module. From the root of your project:
python -m venv .venv
This creates a directory called .venv containing a Python
interpreter and an empty site-packages. The leading dot is
conventional — it suggests "machine-specific, don't commit", and
most editors recognise the name automatically. Add .venv/ to
your .gitignore.
Activating¶
Activating a venv updates your shell's PATH so that python and
pip resolve to the venv's copies, not the system ones. The
activation command differs by shell:
# macOS / Linux (bash, zsh)
source .venv/bin/activate
# Windows (PowerShell)
.venv\Scripts\Activate.ps1
# Windows (cmd)
.venv\Scripts\activate.bat
Most shells will then prefix your prompt with (.venv) so you can
see at a glance that the environment is active.
What changes when you activate¶
which python # /your/project/.venv/bin/python
python --version # whatever Python you used to create the venv
pip list # only pip and setuptools — a clean slate
Anything you pip install from now on lands in
.venv/lib/.../site-packages/. When you python my_script.py,
you're using the venv's interpreter, which can only see its own
installed packages.
Deactivating¶
deactivate
That's a function provided by the activation script — there's
nothing to install. Your PATH reverts to whatever it was before.
Per-project workflow¶
The reliable pattern, applied identically to every Python project:
cd my-project
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt # or pip install -e .
And on subsequent days:
cd my-project
source .venv/bin/activate
# … work …
deactivate
Some teams find activation tedious and reach for a tool that does it automatically — direnv, mise, or one of the unified tools below.
Beyond venv¶
venv is in the standard library and Just Works. A few alternatives
worth knowing about:
- uv. A fast, all-in-one tool that handles venvs, dependency resolution, and lock files with a single command. Increasingly the default in modern Python tooling.
- conda. Used heavily in scientific Python; manages non-Python dependencies (CUDA, system libraries) alongside Python ones.
- pipx. Specifically for installing Python applications (CLIs
like
blackorruff) into their own venvs without you having to manage them. - Poetry, Hatch, PDM. Project managers that wrap venv creation alongside packaging.
For learning Python — and for everything in this guide — venv is
enough. Pick one of the above when a project's needs warrant it.
Recap and next steps¶
- One venv per project; create with
python -m venv .venv. - Activate to switch your shell to the venv's
pythonandpip. - Add
.venv/to.gitignore.
Now that you can install things cleanly, the next step is putting your own code into installable shape — Authoring a package.