M
MeshWorld.
Python Virtual Environments venv uv Developer Tools How-To Beginner 7 min read

Python Virtual Environments: venv, uv, and When to Use Each

Vishnu
By Vishnu

:::note[TL;DR]

  • Virtual environments isolate project dependencies — each project gets its own packages and Python version
  • venv is built into Python: python3 -m venv .venv then source .venv/bin/activate
  • uv is the modern replacement — 10–100x faster installs, manages Python versions, no pyenv needed
  • Always name it .venv — editors and .gitignore templates recognize it automatically
  • Commit requirements.txt or uv.lock, never the .venv directory 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.

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.txt takes 3 minutes. You swap in uv pip install -r requirements.txt and 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

Taskvenvuv
Create envpython3 -m venv .venvuv venv
Activatesource .venv/bin/activatesame
Install packagepip install Xuv pip install X or uv add X
Install from filepip install -r requirements.txtuv pip install -r requirements.txt
Freeze depspip freeze > requirements.txtuv pip freeze > requirements.txt
Install Python versionmanual/pyenvuv python install 3.12
Speedbaseline10-100x faster

Related: Python Cheat Sheet


Summary

  • Virtual environments isolate project dependencies so different projects can use different package versions without conflict
  • venv is built into Python and works everywhere — python3 -m venv .venv then source .venv/bin/activate
  • uv is the modern replacement — 10–100x faster installs, manages Python versions too, increasingly the default in 2026
  • Always name your environment .venv — editors, linters, and .gitignore templates recognize it automatically
  • Commit requirements.txt or uv.lock, never the .venv directory 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.