:::note[TL;DR]
- Virtual environments isolate project dependencies — each project gets its own packages and Python version
venvis built into Python:python3 -m venv .venvthensource .venv/bin/activateuvis the modern replacement — 10–100x faster installs, manages Python versions, nopyenvneeded- Always name it
.venv— editors and.gitignoretemplates recognize it automatically - Commit
requirements.txtoruv.lock, never the.venvdirectory itself :::
A Python virtual environment is an isolated directory that contains its own Python interpreter and packages. When you install something in a virtual environment, it doesn’t touch your system Python or any other project. Each project gets its own sandbox.
Without virtual environments, all your Python projects share the same global packages. Project A needs requests==2.28, project B needs requests==2.31. One of them breaks. This is the problem virtual environments solve.
The two tools worth knowing in 2026
venv — built into Python (3.3+). No install needed. The standard, simple option.
uv — new Rust-based tool from Astral. 10-100x faster than pip. Manages Python versions too. Increasingly the default for new projects in 2026.
Using venv (built-in)
# Create a virtual environment
python3 -m venv .venv
# Activate (macOS/Linux)
source .venv/bin/activate
# Activate (Windows)
.venv\Scripts\activate
# Your prompt changes to show (.venv)
(.venv) $
# Install packages — goes into .venv, not system Python
pip install requests flask
# See installed packages
pip list
# Save dependencies to a file
pip freeze > requirements.txt
# Install from requirements.txt
pip install -r requirements.txt
# Deactivate
deactivate
:::tip
Always name your virtual environment .venv, not env, venv, or anything else. VS Code, PyCharm, and most .gitignore templates automatically recognize .venv — using a different name means configuring each tool manually.
:::
Always name it .venv — most editors, linters, and .gitignore templates recognize this name automatically.
Using uv (recommended for new projects)
uv is a modern replacement for pip, venv, and pyenv combined. Install it once:
curl -LsSf https://astral.sh/uv/install.sh | sh
# or: pip install uv
# Create a virtual environment
uv venv
# Activate (same as venv)
source .venv/bin/activate
# Install packages (much faster than pip)
uv pip install requests flask
# Install from requirements.txt
uv pip install -r requirements.txt
# Install specific Python version
uv venv --python 3.12
# Run a script without activating
uv run script.py
uv pip install is significantly faster than pip install — it resolves dependencies in parallel and caches aggressively. On a cold install of a medium-size project (50+ packages), you’ll feel the difference.
The scenario: You’re onboarding a new project with 80 dependencies.
pip install -r requirements.txttakes 3 minutes. You swap inuv pip install -r requirements.txtand it finishes in 12 seconds. You don’t change anything else. That’s the uv pitch.
Project workflow with uv (modern approach)
# Start a new project
uv init my-project
cd my-project
# Add dependencies (creates/updates pyproject.toml and uv.lock)
uv add requests
uv add flask
uv add pytest --dev
# Install all deps from lock file
uv sync
# Run your code
uv run main.py
# Run tests
uv run pytest
uv init creates a pyproject.toml (modern standard) and a uv.lock file (deterministic installs). This is the equivalent of package.json + package-lock.json in the Python world.
Which Python version does my venv use?
The virtual environment uses whatever Python you called to create it:
# Check your Python
python3 --version
# Create venv with a specific version (if installed)
python3.12 -m venv .venv
# With uv — installs and uses Python 3.12 automatically
uv venv --python 3.12
Managing Python versions with uv
# Install Python versions
uv python install 3.11
uv python install 3.12
uv python install 3.13
# List installed versions
uv python list
# Use a specific version for a project
uv venv --python 3.11
This replaces pyenv for most use cases.
What to add to .gitignore
.venv/
__pycache__/
*.pyc
*.pyo
.env
Commit requirements.txt or uv.lock (the dependency lockfile) — not the .venv directory. Other developers recreate the venv from the lockfile.
VS Code setup
VS Code detects virtual environments automatically if you name yours .venv. Open the command palette → Python: Select Interpreter → choose the .venv entry.
If it doesn’t appear, set it manually:
.venv/bin/python (macOS/Linux)
.venv\Scripts\python.exe (Windows)
Common mistakes
Committing .venv to git. It’s large, OS-specific, and unnecessary. Use .gitignore.
Installing globally because activation is inconvenient. Set up your editor to activate automatically, or use uv run which doesn’t require activation.
Using pip without a virtual environment. Everything lands in system Python. Use pip install --user at minimum, or better, always work inside a venv.
Not pinning versions. pip freeze > requirements.txt captures exact versions. Without it, pip install installs latest, which can break your project when a dependency releases a breaking change.
:::warning
Never commit the .venv directory to git. It’s large (often 100–500 MB), OS-specific, and contains absolute paths — it won’t work on another machine or OS. Add .venv/ to .gitignore and commit requirements.txt or uv.lock instead. Anyone cloning the repo recreates the venv from the lockfile.
:::
Quick reference
| Task | venv | uv |
|---|---|---|
| Create env | python3 -m venv .venv | uv venv |
| Activate | source .venv/bin/activate | same |
| Install package | pip install X | uv pip install X or uv add X |
| Install from file | pip install -r requirements.txt | uv pip install -r requirements.txt |
| Freeze deps | pip freeze > requirements.txt | uv pip freeze > requirements.txt |
| Install Python version | manual/pyenv | uv python install 3.12 |
| Speed | baseline | 10-100x faster |
Related: Python Cheat Sheet
Summary
- Virtual environments isolate project dependencies so different projects can use different package versions without conflict
venvis built into Python and works everywhere —python3 -m venv .venvthensource .venv/bin/activateuvis the modern replacement — 10–100x faster installs, manages Python versions too, increasingly the default in 2026- Always name your environment
.venv— editors, linters, and.gitignoretemplates recognize it automatically - Commit
requirements.txtoruv.lock, never the.venvdirectory itself
Frequently Asked Questions
Do I need a virtual environment for every Python project?
Yes. Without one, all packages install into your system Python. Project A needs requests==2.28, project B needs requests==2.31 — one of them breaks. Virtual environments are the standard solution and take seconds to set up.
What’s the difference between venv, virtualenv, conda, and uv?
venv is built into Python (3.3+) — simple, no install needed. virtualenv is an older third-party tool with slightly more features. conda manages Python environments and non-Python packages, common in data science. uv is the newest and fastest — it replaces pip, venv, and pyenv in one tool.
Why does my VS Code not use the virtual environment automatically?
VS Code needs to know which Python interpreter to use. Open the command palette (Ctrl+Shift+P) → Python: Select Interpreter → choose the .venv/bin/python entry. If it doesn’t appear, set the path manually. Once set, VS Code uses the venv for linting, tests, and the integrated terminal.
What to Read Next
- Python Cheat Sheet — the full Python syntax reference
- Python List Comprehensions Explained — one of the first features worth mastering after the basics