venv in Python: creating a virtual environment with nothing to install

venv creates a Python virtual environment with nothing to install: the module ships with Python since 3.3, and a single command is enough.
5 min read
Believemy logo

Definition

Installing a library with pip drops it somewhere on the machine, and by default that place is a single one: the system Python. The trouble starts as soon as a second project needs a different version of the same library. Both fight over the same folder, the latest install overwrites the previous one, and one of the two projects starts failing without anything having changed in its own code.

venv answers that problem by giving each project its own folder: a copy of the interpreter plus a stock of libraries that belong to that project alone. It is the standard library module that creates this virtual environment, introduced by PEP 405 and shipped with Python since version 3.3: nothing to download, nothing to install before using it.

Creating one takes a single command, followed by a second one that activates the environment.

BASH
python -m venv .venv
source .venv/bin/activate
.venv\Scripts\activate

The second line applies to macOS and Linux, the third to Windows. Once the environment is active, pip install drops libraries into that folder instead of the system Python, which settles exactly the conflict described above. The environment name then shows up at the start of the terminal prompt, a simple visual cue.


What the folder actually holds

Venv does nothing sophisticated: it creates a tree of ordinary files and adjusts a single setting.

ItemRole
bin/ or Scripts/The interpreter and the installed commands
lib/.../site-packages/The libraries downloaded from PyPI
pyvenv.cfgThe version and path of the original Python

Activating the environment does exactly one thing: it puts its executables folder at the front of the PATH, so that python and pip point at the ones inside the environment rather than the system ones. That is also why activation can be skipped entirely: calling .venv/bin/python directly produces the same result, which is what most deployment scripts do.

Good to know

The command to leave the environment is deactivate, added automatically by venv: nothing extra to install to get it.


venv against its alternatives

The question comes back with every new project: does venv suffice, or is a fuller tool needed? The answer depends on what the project actually requires.

ToolWhat it addsWhat it costs
venvNothing to install, available everywhereHandles neither Python versions nor dependency locking
virtualenvFaster, compatible with older Python releasesOne more external dependency to install
poetryEnvironment, dependencies and publishing in one pieceA configuration format and habits to learn
condaAlso installs compiled non-Python librariesA parallel ecosystem, heavy outside scientific computing

For an exercise, a script, a personal project or a repository others will clone, venv is enough and carries the advantage of being understood by everyone. A fuller tool earns its place mostly when the project becomes a published package, or when several machines must end up with exactly the same versions.


The mistakes of the first weeks

Most of the trouble people run into with venv comes down to an easy slip made early on, not to the tool itself.

Warning

Installing a library without having activated the environment is the most common mistake. pip does install something, but into the system Python, not the project folder, and the program then fails with a ModuleNotFoundError on the first import.

The reflex that settles the question holds two checks: which Python answers, and where it installs.

BASH
which python
python -m pip install requests

From the REPL, reading sys.executable gives the same answer with no ambiguity: if the printed path does not run through the project folder, the environment is not active.

A second mistake is pushing the .venv folder into the Git repository. It is heavy, it holds absolute paths tied to a single machine, and it is useless to anybody else. What actually gets shared is the requirements.txt, which rebuilds the environment in a single command.

A third mistake comes from a project folder that gets moved or renamed: the scripts in the executables folder keep the original absolute path in memory and stop working. The fix deserves no effort at all: delete the folder and recreate it.


When it is of no use

A virtual environment isolates dependencies from one another. A script that only imports the standard library has nothing to isolate, and creating a venv out of habit lengthens the setup without protecting anything.

Containers are the more debated case. A Docker image runs a single application, and isolation already exists at the level of the image: many teams install libraries straight into the container's Python. Others still keep a virtual environment, so the launch command stays identical locally and in production.


Frequently asked questions

Question

One environment per project, or a single one for everything?

One per project, and that is the whole point of the approach. Two projects may require two incompatible versions of the same library, and a shared environment brings back exactly the problem venv is meant to remove. The cost is nil: an environment is recreated in a few seconds.

Question

Can the Python version of the environment be chosen?

Yes, but indirectly: venv takes the version of the interpreter that created it. The command python3.12 -m venv .venv yields a 3.12 environment, provided that version is already installed on the machine. Installing several Python versions remains the job of another tool, such as pyenv.

Question

Is activation really mandatory?

No, it is only a convenience. Calling .venv/bin/python my_script.py produces the same result without changing anything in the terminal, and it is the form used in scheduled jobs, containers and pytest commands launched by a continuous integration tool.

Related terms

Discover our python glossary

Browse the terms and definitions most commonly used in development with Python.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.