2025, Dec 28 15:00
Python venv vs pyenv: what venv really does, what it doesn't, and how to manage Python versions
Confused by Python venv vs pyenv? Learn why venv isolates dependencies only, not versions, and how to install and switch Python interpreters reliably.
When the Python docs say that the built-in venv is “recommended for creating virtual environments”, it’s easy to assume this is an all-in-one replacement for third‑party tooling like pyenv. The confusion usually starts here: venv is native and official, so where’s the official way to install, uninstall, list, and switch Python versions across projects and machines?
What the phrase really means
recommended for creating virtual environments
That recommendation is about isolation of dependencies, not version management. venv creates an environment that mirrors the Python interpreter you used to invoke it. It does not install new Python versions, it does not switch the interpreter for you, and it does not manage multiple Python versions.
Reproducing the expectation gap
The core misunderstanding surfaces when you expect venv to select a Python version. In reality, venv simply uses the one you call it with. You can see this by creating environments with different interpreter entry points on the same machine:
python -m venv .env_default
python3.10 -m venv .env_310
python3.11 -m venv .env_311
python3.12 -m venv .env_312
Each environment will reflect the interpreter version that invoked venv. If venv was called using python3.10, the environment will have 3.10. If it was called with 3.12, it will have 3.12. There’s no hidden version switching going on, only straightforward inheritance from the calling interpreter.
What’s actually the problem
The problem isn’t with venv; it’s with expectations. venv is a solid, built-in tool for dependency isolation, but it only works with the current Python version you run it with. By contrast, pyenv targets a different need: it manages multiple Python versions themselves. That includes installing, removing, and switching between interpreters system-wide, per-user, or per-project. One manages packages and isolation within a given interpreter, the other manages the interpreters.
So what’s the official, cross‑platform answer?
There isn’t one. There is no official, cross‑platform tool from Python for installing and switching between multiple Python versions. The built-in venv doesn’t do that job. Third‑party tools like pyenv exist for version management, and they can be used alongside venv as part of the same workflow.
Practical way forward
If you need a specific Python version in a project, invoke venv with that interpreter. That’s the invariant here. You’re not switching versions; you’re choosing which Python creates the environment. You can do that repeatedly for as many versions as you have installed:
python3.10 -m venv .proj_env_310
python3.11 -m venv .proj_env_311
python3.12 -m venv .proj_env_312
This approach makes the behavior explicit and predictable. If you also need to install or switch between Python versions themselves, bring in a dedicated version manager. venv will continue to do what it does best: isolate dependencies within the chosen interpreter.
Why this distinction matters
Conflating virtual environments with interpreter management leads to brittle workflows and puzzling results. Understanding that venv uses the Python version that invoked it removes the ambiguity. It also makes team practices clearer: one tool for managing interpreters, another for per-project isolation. The two are not in competition and can be used together without friction.
Takeaways
Use venv when you want isolated environments for the Python you already have. Expect it to mirror the interpreter that calls it, nothing more. If you need to install, remove, or switch Python versions across contexts, that’s outside venv’s scope. There is no official, cross‑platform solution for that; a third‑party tool fills the gap. Keeping this mental model prevents mismatched expectations and makes your environments intentional and reproducible.