Every Python project should have its own virtual environment. Without one, every pip install lands in a global Python that bleeds between projects, breaks system tools, and makes deployments unpredictable. Virtual environments solve this cleanly.
Quick Reference
| Task | Command |
|---|---|
| Create venv | python -m venv .venv |
| Activate (Linux/Mac) | source .venv/bin/activate |
| Activate (Windows CMD) | .venv\Scripts\activate |
| Activate (Windows PowerShell) | .venv\Scripts\Activate.ps1 |
| Deactivate | deactivate |
| Install package | pip install requests |
| Install from requirements | pip install -r requirements.txt |
| Freeze dependencies | pip freeze > requirements.txt |
| List installed packages | pip list |
| Upgrade pip | python -m pip install --upgrade pip |
| Delete venv | rm -rf .venv |
| Check Python path | which python (Linux/Mac) |
Why Virtual Environments?
Without a venv, running pip install flask installs Flask into the system Python. Every project shares that installation. When project A needs Flask 2 and project B needs Flask 3, one of them breaks. If you upgrade Flask globally, you may break a working project.
A virtual environment is a self-contained copy of Python with its own site-packages folder. Packages installed inside it are isolated from everything else.
Creating a Virtual Environment
The built-in venv module has been included with Python since version 3.3:
python -m venv .venv
This creates a .venv/ folder in the current directory containing:
- A Python interpreter copy (or symlink)
- A fresh
pip - An empty
site-packages/folder
Why .venv (dot prefix)? Convention. The dot hides it from ls by default on Linux/Mac and signals that it's not source code. Many editors (VS Code, PyCharm) detect .venv automatically.
Name Options
# Most common (recommended)
python -m venv .venv
# Some teams prefer without dot
python -m venv venv
# Name it after the project (useful when juggling multiple envs outside project folders)
python -m venv my-project-env
Specify a Python Version
# Requires that Python version to be installed
python3.11 -m venv .venv
python3.12 -m venv .venv
# Check which version was used
.venv/bin/python --version # Linux/Mac
.venv\Scripts\python --version # Windows
Activating the Environment
Activation modifies your shell's PATH so that python and pip point into .venv instead of the system.
# Linux / macOS (bash, zsh, fish)
source .venv/bin/activate
# Windows Command Prompt
.venv\Scripts\activate
# Windows PowerShell
.venv\Scripts\Activate.ps1
# Windows Git Bash
source .venv/Scripts/activate
After activation your prompt changes:
(.venv) user@machine project %
Verify you're using the right Python:
which python # Linux/Mac → /project/.venv/bin/python
where python # Windows → C:\project\.venv\Scripts\python.exe
Deactivate
deactivate
Your prompt returns to normal and python points back to the system interpreter.
Installing Packages
With the venv active, use pip normally:
pip install requests
pip install flask==3.0.0 # specific version
pip install "django>=4.2,<5.0" # version range
pip install requests[security] # extras
Packages install into .venv/lib/pythonX.X/site-packages/.
Upgrading Pip Itself
New venvs often ship with an older pip. Upgrade first:
python -m pip install --upgrade pip
Always use python -m pip rather than just pip to ensure you're upgrading the pip inside the active venv.
requirements.txt
requirements.txt is the standard way to record a project's dependencies so others can reproduce the exact environment.
Freeze Current Environment
pip freeze > requirements.txt
This outputs every installed package with its exact version:
certifi==2024.2.2
charset-normalizer==3.3.2
idna==3.6
requests==2.31.0
urllib3==2.2.1
Install from requirements.txt
pip install -r requirements.txt
Two-File Pattern
pip freeze includes transitive dependencies (urllib3, certifi, etc.). Many projects use two files:
requirements.in ← only direct deps you chose (e.g., requests==2.31.0)
requirements.txt ← full pinned output from pip freeze
Install direct deps from .in, then freeze the full set to .txt. Tools like pip-compile automate this.
.gitignore
Never commit the .venv folder — it's large, platform-specific, and regeneratable:
# Python
.venv/
venv/
env/
__pycache__/
*.pyc
*.pyo
.Python
*.egg-info/
dist/
build/
Do commit requirements.txt (and requirements.in if you use it).
Project Workflow
A typical workflow from scratch:
# 1. Create project folder
mkdir my-project && cd my-project
# 2. Create virtual environment
python -m venv .venv
# 3. Activate
source .venv/bin/activate # Linux/Mac
# 4. Upgrade pip
python -m pip install --upgrade pip
# 5. Install dependencies
pip install flask requests python-dotenv
# 6. Freeze
pip freeze > requirements.txt
# 7. Work on code...
# 8. Deactivate when done
deactivate
When cloning someone else's project:
git clone https://github.com/example/project
cd project
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
VS Code Integration
VS Code detects .venv automatically. To confirm:
- Open Command Palette → Python: Select Interpreter
- Choose
.venv/bin/python(or.venv\Scripts\python.exe)
The integrated terminal then opens with the venv already activated. The status bar shows the active interpreter.
Alternatives to venv
| Tool | What It Does | When to Use |
|---|---|---|
| venv (built-in) | Isolated environment only | Most projects — simple and built-in |
| uv | Ultra-fast venv + pip replacement (Rust) | Speed-critical setups, modern workflow |
| Poetry | Dependency management + packaging + venv | Libraries you publish to PyPI |
| Pipenv | Combines pip + venv + Pipfile | Legacy projects that already use it |
| conda | Env + package manager (not just Python) | Data science, non-Python system packages |
| pyenv | Manage multiple Python versions | Need Python 3.10 and 3.12 side by side |
For most new projects: venv for simplicity, or uv if you want speed (it's 10–100× faster than pip).
uv Quick Start
# Install uv
pip install uv
# or: curl -LsSf https://astral.sh/uv/install.sh | sh
# Create and activate venv via uv
uv venv .venv
source .venv/bin/activate
# Install packages (much faster than pip)
uv pip install flask requests
uv pip freeze > requirements.txt
Common Mistakes
| Mistake | Problem | Fix |
|---|---|---|
Running pip install without activating |
Installs globally | Always activate first; check which python |
Committing .venv/ |
Bloats repo, breaks other OS | Add .venv/ to .gitignore |
pip freeze > requirements.txt in wrong env |
Wrong packages frozen | Verify venv is active before freezing |
Using python3 after activation |
May bypass venv on some systems | Inside venv, use python (not python3) |
| Deleting venv and losing track of dependencies | Can't recreate env | Always keep requirements.txt up to date |
| Sharing venv between projects | Packages bleed between projects | One venv per project |
Not pinning versions in requirements.txt |
pip install requests gets latest, breaks later |
Pin with pip freeze or use == in .in file |
6 FAQ
Q: Should I name it .venv or venv?
Either works. .venv is the most common convention and is the default expected by VS Code's Python extension. The Python docs use venv.
Q: My PowerShell says "running scripts is disabled".
Run: Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser. This allows local scripts (like the venv activation script) to run.
Q: How do I know which Python my venv uses?
Run python --version after activating. To check the path: python -c "import sys; print(sys.executable)".
Q: Should I use python -m venv or virtualenv?
python -m venv is built-in since Python 3.3 — no installation needed. virtualenv is a third-party tool with extra features (Python 2 support, faster creation, --copies). For new projects, the built-in venv is sufficient.
Q: How do I use a venv with Docker? In Docker you usually don't need venv — each container is already isolated. However, some people use venv inside Docker to separate system packages from app packages, or to cache the pip layer. It's optional.
Q: Can I move or rename the venv folder?
No — the venv contains hard-coded absolute paths. If you move it, scripts will break. Delete the old one and create a new one: rm -rf .venv && python -m venv .venv && pip install -r requirements.txt.