Skip to main content
← All Articles · · 14 min read

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.

pythonvirtual-environmentpyenvvenvcondauvpython-toolsdependency-management

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

ToolWhat It DoesBest For
venvCreates isolated Python environmentsAny Python project, built-in, no install needed
pyenvManages multiple Python versionsSwitching between Python 3.10, 3.11, 3.12, etc.
condaManages environments + packages (including non-Python)Data science, ML, scientific computing
uvUltra-fast modern package manager + env managerSpeed, 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 .venv folder. Add it to .gitignore.
  • Use python -m pip instead of bare pip to avoid using the wrong pip binary.
  • For Python version pinning without pyenv, use a .python-version file and document your required version in README.md.
  • python3 -m venv --upgrade .venv upgrades 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, or pytorch
  • 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 install first when possible — it handles dependency resolution better for scientific packages
  • Use pip install only 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

Featurevenvpyenvcondauv
Built into Python✅ Yes❌ No❌ No❌ No
Manages Python versions❌ No✅ Yes✅ Yes✅ Yes
Non-Python packages❌ No❌ No✅ Yes❌ No
Install speedSlow (pip)Slow (pip)Medium⚡ Fast (Rust)
Disk usageSmallMediumLargeSmall-Medium
Data science supportBasicBasicExcellentGood
Modern project format❌ No❌ No❌ No✅ Yes
Windows support✅ GoodLimited✅ Good✅ Good
Learning curveLowLowMediumLow-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.txt for venv projects
  • uv.lock for uv projects
  • environment.yml with 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.

Free Download

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.