Python Virtual Environments Complete Guide: venv, pyenv, conda, and uv (2026)
Master Python virtual environments with this complete guide covering venv, pyenv, conda, and uv. Learn when to use each tool, step-by-step setup, comparison tables, and best practices to avoid dependency hell.
Python Virtual Environments Complete Guide: venv, pyenv, conda, and uv (2026)
If you’ve ever typed pip install requests and broken another project, or opened a repo after six months only to find nothing works — you already understand why Python virtual environments exist. They’re not optional. They’re how professional Python developers avoid dependency hell.
This guide covers everything: why virtual environments matter, the four major tools (venv, pyenv, conda, uv), a side-by-side comparison, step-by-step setup for each, and the pitfalls you’ll hit along the way.
Why Python Virtual Environments Matter
Python’s default behavior is to install packages globally — into the system Python installation. That sounds convenient until you have two projects:
- Project A needs
Django 4.2 - Project B needs
Django 3.2(legacy, can’t upgrade)
There’s no way to install both globally. One will overwrite the other. Virtual environments fix this by giving each project its own isolated Python environment with its own packages, its own pip, and optionally its own Python version.
What a virtual environment actually is:
A virtual environment is a directory containing a Python interpreter (or a symlink to one), a pip binary, and a site-packages folder for installed libraries. When you activate it, your shell’s PATH is updated to prefer that directory’s binaries over system-wide ones.
Benefits:
- Reproducible environments — exact same packages across machines
- No conflicts between projects
- Easy cleanup — delete the folder, done
- Safe to experiment without breaking anything
The Four Main Tools: A Quick Overview
| Tool | What It Does | Best For |
|---|---|---|
| venv | Creates isolated Python environments | Any Python project, built-in, no install needed |
| pyenv | Manages multiple Python versions | Switching between Python 3.10, 3.11, 3.12, etc. |
| conda | Manages environments + packages (including non-Python) | Data science, ML, scientific computing |
| uv | Ultra-fast modern package manager + env manager | Speed, modern projects, drop-in pip replacement |
They’re not always alternatives to each other — many developers combine them. For example, pyenv to manage Python versions + venv for isolation, or pyenv + uv for maximum speed.
venv — The Built-In Option
venv has been included in Python since 3.3. It’s not the flashiest tool, but it requires zero installation and works everywhere.
When to Use venv
- You already have the right Python version installed
- You want the simplest, most portable solution
- You’re on a production server where installing extra tools is friction
- You’re writing library code for others to use
Step-by-Step Setup
1. Create a virtual environment:
python3 -m venv .venv
This creates a .venv directory in your current folder. The convention is to use .venv (with a dot) so it’s hidden by default and excluded by most .gitignore templates.
2. Activate it:
# macOS / Linux (bash/zsh)
source .venv/bin/activate
# Windows (PowerShell)
.venv\Scripts\Activate.ps1
# Windows (Command Prompt)
.venv\Scripts\activate.bat
After activation, your prompt changes to show (.venv) and python now points to the environment’s Python.
3. Install packages:
pip install requests flask
4. Save your dependencies:
pip freeze > requirements.txt
5. Recreate on another machine:
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
6. Deactivate:
deactivate
Pro Tips for venv
- Never commit your
.venvfolder. Add it to.gitignore. - Use
python -m pipinstead of barepipto avoid using the wrong pip binary. - For Python version pinning without pyenv, use a
.python-versionfile and document your required version inREADME.md. python3 -m venv --upgrade .venvupgrades the environment’s pip and base packages.
pyenv — Managing Multiple Python Versions
venv gives you isolation, but it doesn’t control which Python version is used. If your project needs Python 3.11 but your system has 3.9, venv can’t help with that. That’s where pyenv comes in.
pyenv lets you install and switch between any Python version — 3.9, 3.10, 3.11, 3.12, 3.13 — and set per-project defaults.
When to Use pyenv
- You maintain multiple projects with different Python version requirements
- You need to test code against multiple Python versions
- Your system Python is outdated and you can’t (or don’t want to) upgrade it
- You’re on macOS or Linux (pyenv works best here)
Installing pyenv
macOS (via Homebrew):
brew install pyenv
Linux:
curl https://pyenv.run | bash
Then add to your shell config (~/.bashrc, ~/.zshrc):
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
Restart your shell or run source ~/.zshrc.
Windows: Use pyenv-win — install via pip install pyenv-win or the official installer.
Common pyenv Commands
# List all installable Python versions
pyenv install --list
# Install a specific version
pyenv install 3.12.3
# Set global default Python
pyenv global 3.12.3
# Set Python version for current directory (creates .python-version file)
pyenv local 3.11.8
# Check current active version
pyenv version
# List installed versions
pyenv versions
pyenv + venv Workflow
The recommended pattern is pyenv for version management + venv for isolation:
# Install and set Python version
pyenv install 3.12.3
pyenv local 3.12.3
# Create venv using that Python
python -m venv .venv
source .venv/bin/activate
# Verify versions
python --version # Python 3.12.3
pip --version
Commit the .python-version file so your teammates get the same Python version automatically (if they also use pyenv).
conda — Environments for Data Science
conda is a different beast. Developed by Anaconda, it manages both Python packages and non-Python dependencies (like CUDA libraries, C extensions, and system-level tools). It’s the standard in data science and machine learning.
When to Use conda
- You’re doing data science, machine learning, or scientific computing
- You need packages like
numpy,pandas,scikit-learn,tensorflow, orpytorch - You need non-Python dependencies (like GDAL for GIS, or CUDA for GPU computing)
- Your team already uses Anaconda/Miniconda
When NOT to Use conda
- Pure web development projects (it’s overkill and slower)
- Projects where you need to minimize disk usage (conda environments are large)
- When you need pip-only packages that aren’t on conda-forge
Installing conda
Option 1 — Miniconda (recommended, minimal):
# macOS/Linux
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh
Option 2 — Anaconda (full distribution with GUI):
Download from the official Anaconda website.
Common conda Commands
# Create a new environment
conda create --name myenv python=3.11
# Activate
conda activate myenv
# Deactivate
conda deactivate
# Install packages
conda install numpy pandas scikit-learn
# Install from conda-forge (more packages)
conda install -c conda-forge some-package
# List environments
conda env list
# Export environment
conda env export > environment.yml
# Recreate from file
conda env create -f environment.yml
# Remove environment
conda env remove --name myenv
The environment.yml File
Instead of requirements.txt, conda uses environment.yml:
name: myproject
channels:
- conda-forge
- defaults
dependencies:
- python=3.11
- numpy=1.26.0
- pandas=2.1.0
- scikit-learn=1.3.0
- pip:
- some-pip-only-package
Notice you can mix conda packages and pip packages in the same file.
conda vs pip: The Rules
- Use
conda installfirst when possible — it handles dependency resolution better for scientific packages - Use
pip installonly for packages not available in conda channels - Don’t mix them recklessly — pip can break conda’s dependency solver
uv — The Modern, Fast Alternative
uv is the newest player, but it’s already reshaping how Python developers work. Built by Astral (the team behind ruff), it’s written in Rust and is 10-100x faster than pip for package installation. It handles virtual environments, package management, and Python version management in a single tool.
When to Use uv
- You want the fastest possible package installation
- You’re starting a new project and want modern tooling
- You’re replacing pip, pip-tools, or virtualenv
- You want a single tool that does everything (like npm or cargo for Python)
- You’re building CI/CD pipelines and want faster installs
Installing uv
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# Or via pip
pip install uv
Core uv Commands
Creating and managing environments:
# Create a virtual environment
uv venv
# Create with specific Python version
uv venv --python 3.12
# Activate (same as standard venv)
source .venv/bin/activate
Installing packages (drop-in pip replacement):
# Install a package
uv pip install requests
# Install from requirements.txt
uv pip install -r requirements.txt
# Install in development mode
uv pip install -e .
# Generate lockfile
uv pip compile requirements.in -o requirements.txt
Project management (modern workflow):
# Initialize a new project
uv init myproject
cd myproject
# Add a dependency
uv add requests
# Remove a dependency
uv remove requests
# Run a command in the project environment
uv run python main.py
uv run pytest
# Sync all dependencies
uv sync
# Install Python version
uv python install 3.12
uv python list
The pyproject.toml Workflow with uv
Modern Python projects use pyproject.toml instead of requirements.txt. With uv init, you get:
[project]
name = "myproject"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = [
"requests>=2.31.0",
"fastapi>=0.110.0",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
Running uv add flask automatically updates this file and creates a uv.lock file for reproducible installs.
Why uv is Fast
uv downloads packages in parallel, uses a global cache (so you never download the same package twice), and resolves dependencies using a SAT solver — all implemented in Rust. On cold installs, it’s typically 10-50x faster than pip. On warm cache hits, it’s nearly instant.
Full Comparison Table
| Feature | venv | pyenv | conda | uv |
|---|---|---|---|---|
| Built into Python | ✅ Yes | ❌ No | ❌ No | ❌ No |
| Manages Python versions | ❌ No | ✅ Yes | ✅ Yes | ✅ Yes |
| Non-Python packages | ❌ No | ❌ No | ✅ Yes | ❌ No |
| Install speed | Slow (pip) | Slow (pip) | Medium | ⚡ Fast (Rust) |
| Disk usage | Small | Medium | Large | Small-Medium |
| Data science support | Basic | Basic | Excellent | Good |
| Modern project format | ❌ No | ❌ No | ❌ No | ✅ Yes |
| Windows support | ✅ Good | Limited | ✅ Good | ✅ Good |
| Learning curve | Low | Low | Medium | Low-Medium |
Which Tool Should You Use?
Use venv if:
- You want zero setup time
- You’re on a server or restricted environment
- Your project is simple and doesn’t need version switching
Use pyenv + venv if:
- You work on multiple projects with different Python versions
- You’re on macOS or Linux
- You want the classic, reliable approach
Use conda if:
- You’re doing data science or ML
- You need non-Python dependencies (CUDA, GDAL, etc.)
- Your team already standardized on it
Use uv if:
- You’re starting a new project and want the best modern DX
- CI/CD speed matters to you
- You want one tool to replace pip, pip-tools, and virtualenv
- You like how npm/cargo works and want Python to feel similar
Use pyenv + uv for greenfield projects: This is increasingly the recommended combination for 2026. pyenv manages Python versions at the system level; uv handles everything else.
Best Practices
1. Always Use a Virtual Environment
Never install packages globally. This is the most important rule.
# Wrong
pip install flask
# Right
python -m venv .venv && source .venv/bin/activate && pip install flask
2. Pin Your Python Version
Use either a .python-version file (for pyenv/uv) or specify requires-python in pyproject.toml.
# For pyenv
echo "3.12.3" > .python-version
# For pyproject.toml
requires-python = ">=3.12"
3. Commit Lock Files, Not Just Requirement Files
requirements.txt with unpinned versions leads to different installs over time. Use:
pip freeze > requirements.txtfor venv projectsuv.lockfor uv projectsenvironment.ymlwith pinned versions for conda
4. Use .gitignore Properly
# .gitignore
.venv/
venv/
__pycache__/
*.pyc
.python-version # optional, some teams commit this
5. Document Your Setup
Every project should have a setup section in README.md:
## Setup
```bash
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
### 6. Separate Dev and Production Dependencies
```bash
# Production
pip install -r requirements.txt
# Development (tests, linters, formatters)
pip install -r requirements-dev.txt
With uv and pyproject.toml:
[project.optional-dependencies]
dev = ["pytest", "ruff", "mypy"]
Common Pitfalls and How to Avoid Them
Pitfall 1: Running pip without activating the environment
You type pip install flask but forget to activate first. The package installs globally. Solution: check your prompt — it should show (.venv) when active.
Pitfall 2: Committing .venv to git
The .venv folder can be hundreds of MB. Always add it to .gitignore.
Pitfall 3: Different Python versions on different machines
Use pyenv or uv to pin the Python version. Never assume the system Python is “good enough.”
Pitfall 4: Mixing conda and pip recklessly
Install as much as possible with conda install first, then use pip install only for packages not in conda. Mixing them in the wrong order can corrupt the environment.
Pitfall 5: Deleting the environment without deactivating
Run deactivate before deleting the .venv folder. Otherwise your shell still points to a dead Python binary.
Quick Reference Cheatsheet
# venv
python3 -m venv .venv
source .venv/bin/activate
pip install package
pip freeze > requirements.txt
deactivate
# pyenv
pyenv install 3.12.3
pyenv local 3.12.3
pyenv version
# conda
conda create -n myenv python=3.11
conda activate myenv
conda install numpy
conda env export > environment.yml
conda deactivate
# uv
uv venv
uv pip install package
uv add package # project mode
uv run python script.py # run without activating
uv python install 3.12 # install Python version
uv sync # install all deps from lockfile
Summary
Python virtual environments are non-negotiable for professional Python development. Here’s the recap:
- venv — built-in, simple, reliable. Use it for anything that doesn’t need version switching.
- pyenv — solves the “I have Python 3.9 but need 3.12” problem. Pairs well with venv.
- conda — the data science standard. Handles non-Python deps that pip can’t.
- uv — the fastest tool in 2026. Modern, Rust-powered, and replaces pip + virtualenv + pip-tools.
For new projects in 2026, the recommended stack is pyenv + uv for maximum flexibility and speed. For data science, conda remains the go-to. For simplicity on a quick script or server, venv is always there.
Pick the right tool for the job — then stop worrying about dependencies and start shipping code.
Want to dive deeper? Check out our guides on Docker for containerized Python apps and environment variables best practices.
50 CLI Commands That Save Hours Every Week
The exact Git shortcuts, file search tricks, Docker commands, and productivity hacks that senior developers use daily. Compiled from 5+ years of shipping production code.
- Git mastery (10 cmds)
- File & search wizardry
- Docker & DevOps tricks
- Process & network tools
- Productivity boosters
- macOS & Linux install guide
No spam. 1 email/week max. Unsubscribe anytime.
Found this guide useful? Check out our free developer tools.
Affiliate disclosure: Some links below are affiliate links — we may earn a small commission at no extra cost to you. Learn more.
Recommended Tools & Resources
DigitalOcean
$200 credit for new users. Simple, affordable cloud hosting for developers.
GitHub Student Pack
Free access to 100+ developer tools. Perfect for students and new devs.
Vercel
Deploy frontend apps instantly. Free tier is generous for side projects.
DevPlaybook Products
Boilerplates, scripts & AI toolkits to 10x your dev workflow.