Python `venv` on macOS Is Still the Right Default for Project Dependencies, Even If You Use `uv`
A practical Python virtual environment guide for macOS that explains why venv still matters, how to create and recreate environments cleanly, and why project dependencies should remain disposable rather than global.
Why this still matters in 2026: new Python tools keep improving the packaging story, but the core mistake never changes. Developers install project dependencies into the wrong place, then blame Python for being chaotic instead of admitting the environment boundary was never made explicit.
What venv is really giving you
venv creates an isolated Python environment for a project. The important part is not the command itself. It is the mindset behind it: project dependencies belong to the project, not to your whole machine.
That means the environment should be:
- isolated
- disposable
- recreatable
Once you accept those three ideas, a lot of Python frustration goes away.
Create a virtual environment
Inside a project:
python3 -m venv .venvActivate it in zsh:
source .venv/bin/activateNow python and pip commands inside that session resolve to the virtual environment instead of the base interpreter.
Why this is still the sane default
Even if you use newer tools such as uv, the project still benefits from a clearly bounded environment. Tooling may get faster, but the separation problem does not disappear.
The real enemy is not whether the environment was created by one tool or another. The enemy is blurred dependency scope.
The mistake people keep making
They install packages globally because the project is “small” or “temporary.” That seems harmless until:
- another project needs a different version
- the machine accumulates stale packages
- reinstalling or sharing the project becomes harder
- debugging starts with “which interpreter is this using?”
That is not Python being unreasonable. That is the cost of skipping isolation.
Why recreatability matters
The Python docs explicitly frame virtual environments as disposable. That is one of the healthiest ways to think about them. If the environment becomes weird, delete it and recreate it rather than treating it like precious local state.
That habit changes the emotional tone of Python setup. Broken environment? Rebuild. Not because the tooling is weak, but because the environment boundary is intentionally lightweight.
Why this still helps even with newer tools
Modern tools can improve speed, lockfile behavior, or dependency management, but they still benefit from a clean environment boundary. The older venv habit remains useful because it teaches the right scope: packages belong to the project, not to your whole laptop.
That scope discipline is the real lesson people keep rediscovering under newer tooling names.
The packaging stack may evolve, but the environment boundary still matters.
That is why venv keeps surviving every wave of Python tooling discussion.
It keeps solving the same real problem: project dependency boundaries.
That problem is old, and it is still expensive when ignored.
Reproducible environments are still cheaper than accidental global state.
That is the quiet reason this habit keeps surviving.
Final recommendation
On macOS, keep using a project-local virtual environment unless you have a very specific reason not to. Whether you later layer uv, pip-tools, Poetry, or something else on top, the basic rule still holds: project dependencies should live in a project boundary you can destroy and rebuild without drama.
That discipline is old-fashioned in the best sense. It keeps Python work understandable.