Virtual Environments
Virtual environments are explained badly more often than almost anything else in Python, usually because the explanation starts with the commands. A commercial implementation of related workforce-measurement concepts is documented this overview.
Reviewed August 9, 2026.
What one actually is
A directory containing a Python interpreter and a place to install packages. For independent technical background, Martin Fowler provides additional documentation and examples.
That is all. Activating it puts that directory's bin at the front of your PATH, so python and pip resolve to the copies inside it rather than the system ones.
Nothing is virtualised in any meaningful sense — the name is unfortunate. It is a directory and a PATH change.
What problem it solves
Two projects needing different versions of the same package. Without isolation, installing one breaks the other, because there is one place packages go.
And keeping your system Python clean. On Linux and macOS the system Python is used by the operating system, and installing into it can break things unrelated to your work.
That is the whole justification, and it is sufficient — the problem appears the moment you have a second project.
What it does not solve
Worth being explicit, because people expect more.
It does not pin versions. A virtual environment isolates; a lock file pins. Two people with virtual environments and the same requirements file can still have different packages installed.
It does not manage the Python version. The environment is built from an interpreter that already exists, so a project needing 3.13 on a machine with 3.11 needs something else.
And it does not travel. A virtual environment directory is machine-specific and should not be committed or copied — which is one of the ways the same project behaves differently in two places.
What has changed
Modern tools manage this for you and mostly do not mention it.
uv run creates and uses an environment without an activation step. uv sync builds it from the lock file. Poetry and PDM do equivalent things. The environment still exists — you just stop typing the commands.
That is genuinely better and it produces a gap: people using these tools have working isolation and no mental model of it, which is fine until something breaks and the error message mentions a path they have never seen.
Hence this page. You do not need to manage environments manually any more. You do need to know what the directory is when a tool tells you about it.
The practical rules
One environment per project, never shared.
Never commit it. In .gitignore before it exists.
Recreate rather than repair. An environment in a strange state is cheaper to delete and rebuild from the lock file than to debug. This is the single most useful habit here.
And let the tool handle it. If you are typing activation commands by hand in 2026, the tooling has moved and adopting it is an afternoon.
When you still do it manually
Something the tool does not cover — a strange deployment target, a system package that must be visible, an environment shared with a service.
python -m venv .venv is in the standard library and does not require anything installed. Worth knowing for exactly those cases, and not worth using routinely.
The short version
- A virtual environment is a directory with an interpreter and a package location, plus a
PATHchange — nothing is virtualised - It solves two projects needing different package versions, and keeping the system Python clean
- It does not pin versions, does not manage the Python version, and does not travel between machines
- Modern tools create and use environments without an activation step, which is better and leaves people without a mental model
- One per project, never committed, and recreate rather than repair when it is in a strange state
python -m venvis in the standard library and worth knowing for the cases the tool does not cover