Virtual Environments
Every Python project depends on a set of third-party packages, and different projects almost never agree on which versions they need. A virtual environment is an isolated, self-contained Python installation — its own interpreter (or a reference to one) and its own site-packages directory — that keeps one project's dependencies from leaking into, or clashing with, another's.
Why virtual environments exist
Without isolation, every package you install with pip goes into a single, global site-packages folder tied to your system Python. That works fine until you have more than one project on the same machine — which is to say, it stops working almost immediately.
Imagine Project A was built against Django 3.2, and Project B — started two years later — requires Django 5.0. Both projects import a package literally named django, so a single global Python installation can only ever satisfy one of them at a time.
Install Django 5.0 globally to work on Project B, and Project A breaks the next time you run it. Downgrade back to 3.2 for Project A, and Project B breaks. Now multiply this across dozens of packages (requests, numpy, SQLAlchemy...) with their own version constraints, and you get dependency hell: a tangle of conflicting requirements where fixing one project's environment silently breaks another's, and there is no single global state that keeps everyone happy.
Virtual environments solve this by giving every project its own private copy of site-packages. Project A can have Django 3.2 installed inside its environment, Project B can have Django 5.0 installed inside its own, and neither installation is aware the other exists.
Creating a virtual environment with venv
Python 3.3+ ships with the venv module in the standard library, so no extra installation is required. From your project's root directory, run:
# Create a virtual environment named "env" in the current directory python -m venv env
This creates a folder called env/ containing a copy (or symlink) of the Python interpreter, a pip installer, and an empty site-packages directory ready for this project's dependencies. Nothing is installed globally, and nothing outside the env/ folder is touched.
The environment folder name is up to you — env, venv, and .venv are the three most common conventions. .venv (with the leading dot) is popular because it hides the folder from most file listings and is the name several editors (VS Code, PyCharm) look for automatically.
Activating and deactivating
Creating the environment isn't enough — you have to activate it in your current shell session so that python and pip point at the environment's copies instead of the system ones. The activation command differs by platform and shell.
Platform | Shell | Activation Command |
|---|---|---|
Windows | cmd.exe | env\Scripts\activate.bat |
Windows | PowerShell | env\Scripts\Activate.ps1 |
macOS / Linux | bash / zsh | source env/bin/activate |
On Windows PowerShell you may hit an error like "running scripts is disabled on this system." That's PowerShell's execution policy blocking the activation script, not a problem with your environment — it can be fixed by adjusting Set-ExecutionPolicy for the current user, or you can activate via cmd.exe instead.
Once activated, your shell prompt is usually prefixed with the environment name (e.g. (env) $), and pip install will install packages only into that environment. When you're done working, leave the environment with a single command that works identically on every platform:
deactivate
Most modern IDEs (VS Code, PyCharm, etc.) automatically detect a venv/.venv folder in your project root and offer to use it as the interpreter for that workspace — you often don't need to activate it manually inside the editor's integrated terminal.
Ignoring the environment folder in git
The environment folder should never be committed to version control. It can easily contain thousands of files, its contents are platform- and machine-specific (absolute paths baked into activation scripts, compiled extensions, etc.), and it is trivially reproducible from a requirements.txt or lock file. Add it to .gitignore:
# .gitignore env/ venv/ .venv/
Anyone cloning the repository re-creates the environment locally with python -m venv env and reinstalls dependencies from the project's requirements file or lock file — that's the whole point of tracking dependencies declaratively instead of shipping the environment itself.
An alternative: conda
conda (from the Anaconda/Miniconda ecosystem) is a popular alternative to venv, especially in data science and scientific computing. Unlike venv, which only isolates packages for whichever Python interpreter created it, conda can install and manage entirely different Python versions per environment, alongside non-Python dependencies (C libraries, compilers, etc.) that pip can't handle on its own.
# Create a conda environment with its own Python 3.11 interpreter conda create -n myenv python=3.11
If your project relies on heavy numerical or ML libraries with native dependencies (numpy, pandas, PyTorch, CUDA toolkits), conda is often the smoother path; for typical web and application development, venv plus pip is usually all you need.
Virtual environments isolate per-project dependencies so different projects can use different, even conflicting, package versions.
python -m venv envcreates one; activation is platform-specific,deactivatealways works the same way.Never commit the environment folder —
.gitignoreit and recreate it from a requirements/lock file instead.condais a heavier alternative that can also manage Python versions and non-Python dependencies.