Python Virtual Environments with venv: Create, Activate, Freeze and Fix
A virtual environment is a folder that contains its own Python interpreter link and its own site-packages, so each project gets the packages and versions it needs without touching the system Python or other projects. Create one with python -m venv .venv, activate it, install with python -m pip install, record the result with pip freeze, and delete the folder whenever you want a clean start.
The venv module ships with Python 3, so there is nothing to install. The examples below were run with Python 3.13 on Linux; the commands are the same on macOS, and Windows differences are shown where they matter.
Why bother with a virtual environment
- Isolation: project A can pin
pandas2.1 while project B uses the latest release, and neither breaks the other. - Reproducibility: the list of installed packages becomes a file you can commit and reinstall on another machine or in CI.
- Safety: you never
pip installinto the interpreter your operating system relies on. On many current Linux distributions and on Homebrew Python, pip refuses to do that anyway (see the error section below). - Disposability: an environment is just a directory. If it gets into a mess, delete it and rebuild it from your requirements file.
Create the environment
Run this from the root of your project. The last argument is the directory to create; .venv is the most common name, and many tools (including VS Code and PyCharm) detect it automatically.
cd my-project
python3 -m venv .venv
On Windows, use the Python launcher so you get the version you expect:
py -m venv .venv
The environment is tied to the interpreter that created it. To build one for a specific version, call that interpreter explicitly, for example python3.12 -m venv .venv or py -3.12 -m venv .venv. If you are not sure which version that is, our guide to checking the Python version shows several ways to find out.
What gets created:
.venv/
├── .gitignore (Python 3.13+: ignores the whole folder)
├── bin/ (Scripts\ on Windows): python, pip, activate scripts
├── include/
├── lib/python3.13/site-packages/
└── pyvenv.cfg
pyvenv.cfg records the base interpreter. In our test it contained:
home = /usr/bin
include-system-site-packages = false
version = 3.13.17
executable = /usr/bin/python3.13
Activate and deactivate
Activation puts the environment's bin (or Scripts) directory first on your PATH, so python and pip refer to the environment's copies. It also prefixes your prompt with the environment name.
# Linux and macOS (bash, zsh)
source .venv/bin/activate
# Windows, Command Prompt
.venv\Scripts\activate.bat
# Windows, PowerShell
.venv\Scripts\Activate.ps1
# any platform, when you are done
deactivate
If PowerShell refuses to run the script because of its execution policy, the venv documentation suggests allowing signed and local scripts for your user only:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Activation is a convenience, not a requirement. Calling the environment's interpreter by its path works without it, which is what you want in scripts, cron jobs and Dockerfiles:
.venv/bin/python -m pip install requests
.venv/bin/python manage.py runserver
Check that you are really inside it
Inside a virtual environment, sys.prefix points to the environment while sys.base_prefix still points to the base installation. Comparing them is the reliable test:
import sys
print(sys.executable)
print(sys.prefix != sys.base_prefix)
/home/me/my-project/.venv/bin/python
True
Outside any environment the second line prints False. On the command line, python -m pip --version shows the path pip is installing into, which catches the classic mistake of running a pip that belongs to another interpreter.
Install, freeze and reinstall packages
Prefer python -m pip to a bare pip: it guarantees that pip runs with the interpreter you just named.
python -m pip install requests
python -m pip freeze
certifi==2026.10.23
charset-normalizer==3.5.2
idna==3.20
requests==2.32.3
urllib3==2.8.0
Your version numbers will differ. pip freeze lists every installed distribution with an exact version, including dependencies you never asked for directly. Save it, commit it, and rebuild the same environment elsewhere:
python -m pip freeze > requirements.txt
# on another machine, after creating and activating a fresh .venv
python -m pip install -r requirements.txt
For a library, or when you want looser constraints, keep a short hand-written list of direct dependencies (in requirements.in or the dependencies table of pyproject.toml) and use the frozen file only for exact deployments. To see what a single package resolved to, see checking a package version with pip.
Keep it out of version control
Commit requirements.txt or pyproject.toml, never the environment itself: it contains absolute paths and platform-specific binaries. Since Python 3.13, venv writes a .gitignore containing * inside the new directory, so Git ignores it automatically; pass --without-scm-ignore-files to skip that. With older versions, add .venv/ to your project's .gitignore yourself.
Useful options
--clearempties an existing environment directory before recreating it: a quick reset.--upgrade-depsupgrades pip in the new environment to the latest release from PyPI.--prompt NAMEchanges the label shown in your prompt, handy when every project uses.venv.--system-site-packageslets the environment see packages installed in the base interpreter. It is occasionally useful for large system-provided libraries, but it weakens isolation.--without-pipcreates the environment without pip, for tools that manage packages differently.
An environment cannot simply be moved or renamed, because scripts inside it contain absolute paths. If you move a project, delete .venv and create it again.
Use it in Jupyter and PyCharm
A notebook server does not automatically use your project environment. Register the environment as a kernel from inside it:
python -m pip install ipykernel
python -m ipykernel install --user --name my-project --display-name "Python (my-project)"
Then pick "Python (my-project)" in the kernel menu. In PyCharm, choose the existing .venv/bin/python (or .venv\Scripts\python.exe) as the project interpreter; our guide to installing Python packages in PyCharm walks through the dialogs.
Fixing "error: externally-managed-environment"
Running pip install against a system Python on recent Debian, Ubuntu, Fedora or Homebrew installations often fails with error: externally-managed-environment. This comes from PEP 668: the distribution marks its Python as managed by the operating system's package manager, and pip refuses to modify it. The fix is not --break-system-packages; it is to do exactly what this article describes:
python3 -m venv .venv
.venv/bin/python -m pip install the-package
If python3 -m venv itself fails on Debian or Ubuntu with a message about ensurepip, install the distribution's venv package (for example python3-venv, or the version-specific python3.X-venv) and try again. For command-line applications you want available everywhere, a tool such as pipx creates one isolated environment per application for you.
Troubleshooting
- "No module named X" although you installed it: you installed into a different interpreter. Compare
python -m pip --versionwithsys.executable. - The prompt shows the environment but
pythonis still the system one: a shell alias or a hard-coded path is winning. Runtype python(bash, zsh) orwhere python(Windows). - Everything broke after upgrading Python: environments point at the interpreter that created them. Delete
.venv, recreate it with the new version and reinstall fromrequirements.txt.
Summary
One project, one .venv: create it with python -m venv .venv, activate it or call .venv/bin/python directly, install with python -m pip, record versions with pip freeze > requirements.txt, keep the folder out of Git, and rebuild it rather than repair it.
Sources
- Python documentation, venv: Creation of virtual environments.
- Python Packaging User Guide, Install packages in a virtual environment using pip and venv.
- Python Enhancement Proposals, PEP 668: Marking Python base environments as "externally managed".
ToolsInstall packages in PyCharm
Install Python packages in PyCharm via the Packages tool window, interpreter settings or pip; venv vs conda, requirements.txt and fixing import errors.
ToolsCheck a package version with pip
Check an installed Python package version with pip show, pip list and pip freeze, or in code with importlib.metadata, and compare versions safely.
ToolsPython version in Jupyter
Check the Python version a Jupyter kernel really runs with sys.version and sys.executable, avoid the !python --version trap and register a venv as a kernel.