A Python virtual environment is an isolated directory tree that contains its own Python interpreter and packages, independent of the system-wide installation. Virtual environments prevent version conflicts between projects — for example, Project A needing Django 4.2 while Project B requires Django 5.0. The Python Packaging Authority (PyPA) recommends always using virtual environments. As of Python 3.12, venv is the built-in standard, but tools like Poetry, uv, pyenv, and conda offer additional capabilities for dependency resolution, Python version management, and reproducible builds. For configuring secrets and runtime settings inside an activated environment, see Python environment variables.
How Does venv Work?
The venv module ships with Python 3.3+ and creates a lightweight virtual environment by symlinking (or copying) the Python binary and creating an isolated site-packages directory. When activated, the shell's PATH is modified so that python and pip point to the environment's copies.
# Create a virtual environment
python3 -m venv .venv
# Activate (Linux / macOS)
source .venv/bin/activate
# Activate (Windows PowerShell)
.venv\Scripts\Activate.ps1
# Verify isolation
which python # → .venv/bin/python
pip list # → only pip and setuptools
# Deactivate
deactivateTip: Always add .venv/ to your .gitignore. The environment itself should never be committed — only the dependency specification file.
How Do You Manage Dependencies with pip?
pip is the standard package installer for Python. Use requirements.txt to pin exact versions for reproducible installs.
# Install packages
pip install requests==2.31.0 flask==3.0.0
# Freeze all installed packages (exact versions)
pip freeze > requirements.txt
# Install from requirements file
pip install -r requirements.txt
# Upgrade a package
pip install --upgrade requests
# Uninstall
pip uninstall requests# Pin exact versions for reproducibility
requests==2.31.0
flask==3.0.0
gunicorn==21.2.0
psycopg2-binary==2.9.9
# Separate dev dependencies in requirements-dev.txt
-r requirements.txt
pytest==7.4.3
black==23.12.1
mypy==1.8.0What Is pyenv and When Should You Use It?
pyenv manages multiple Python versions on a single machine. It intercepts Python commands via shims in your PATH and routes them to the correct version. Use pyenv when different projects need different Python versions (e.g., 3.10 vs 3.12).
# Install a Python version
pyenv install 3.12.1
# Set global default
pyenv global 3.12.1
# Set per-project version (creates .python-version file)
cd my-project
pyenv local 3.11.7
# List installed versions
pyenv versions
# Combine with venv
pyenv local 3.12.1
python -m venv .venv
source .venv/bin/activateHow Does Poetry Handle Virtual Environments?
Poetry is an all-in-one dependency manager that handles virtual environment creation, dependency resolution, and packaging. It uses pyproject.toml for configuration and generates a poetry.lock file for deterministic installs. Poetry automatically creates and manages virtual environments per project.
# Create a new project
poetry new my-project
# Or initialize in an existing directory
poetry init
# Add dependencies
poetry add requests flask
poetry add --group dev pytest black mypy
# Install all dependencies (creates venv automatically)
poetry install
# Run commands inside the virtual environment
poetry run python main.py
poetry run pytest
# Activate the shell
poetry shell
# Export to requirements.txt (for Docker/CI)
poetry export -f requirements.txt --output requirements.txt[tool.poetry]
name = "my-project"
version = "1.0.0"
description = "Example project"
[tool.poetry.dependencies]
python = "^3.11"
requests = "^2.31.0"
flask = "^3.0.0"
[tool.poetry.group.dev.dependencies]
pytest = "^7.4.3"
black = "^23.12.1"
mypy = "^1.8.0"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"How Does uv Compare to Poetry?
uv is a Rust-based, drop-in replacement for pip, pip-tools, virtualenv, pipx, and Poetry from Astral (the team behind Ruff). It reads the same pyproject.toml as Poetry, manages Python versions itself (no pyenv needed), and ships a uv.lock for deterministic installs. Astral's published benchmarks show uv resolving and installing dependencies 10–100× faster than pip, which is why it has become the default recommendation for new Python projects in 2025–2026.
# Install uv (one-time)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Create a virtual environment (defaults to .venv)
uv venv
# Install Python itself if missing
uv python install 3.12
# Add dependencies to pyproject.toml + uv.lock
uv add requests flask
uv add --dev pytest mypy
# Install everything from pyproject.toml / uv.lock
uv sync
# pip-compatible interface (no activation required)
uv pip install requests
uv pip install -r requirements.txt
# Run a command inside the environment
uv run python main.py
uv run pytestWhen Should You Use conda?
conda is a cross-platform package and environment manager that handles both Python and non-Python dependencies (C libraries, CUDA, R, etc.). It is the standard in data science and machine learning because packages like NumPy and TensorFlow often depend on compiled C/Fortran libraries that pip cannot manage. Use conda when your project has non-Python binary dependencies.
# Create an environment with a specific Python version
conda create -n myenv python=3.12
# Activate
conda activate myenv
# Install packages
conda install numpy pandas scikit-learn
# Export environment
conda env export > environment.yml
# Recreate from file
conda env create -f environment.yml
# List environments
conda env list
# Remove an environment
conda env remove -n myenvHow Do These Tools Compare?
| Feature | venv + pip | Poetry | uv | conda | pyenv |
|---|---|---|---|---|---|
| Python version management | No | No | Yes | Yes | Yes |
| Dependency resolution | Basic | Advanced (SAT solver) | Advanced (Rust resolver) | Advanced | N/A |
| Lock file | Manual (pip freeze) | poetry.lock | uv.lock | environment.yml | N/A |
| Non-Python deps | No | No | No | Yes | No |
| Built into Python | Yes | No | No | No | No |
| Best for | Simple projects | Apps & libraries | Modern apps & monorepos | Data science | Multi-version Python |
Common pitfalls
- • Committing the .venv/ directory. Virtual environments are machine-specific and bloat the repo. Add
.venv/to.gitignoreand commit only the dependency manifest (pyproject.toml,requirements.txt, plus the lock file). - • Mixing pip install with Poetry or uv. Running
pip installinside a Poetry/uv-managed environment skips the resolver and lock file, so the nextpoetry install/uv syncwipes your changes. Always go through the project tool (poetry add,uv add). - • Forgetting to activate. A fresh shell starts with the system Python on
PATH. Checkwhich pythonbefore installing — or usepoetry run/uv runto bypass activation entirely. - • Installing into the system Python on macOS. The Apple-bundled Python is read-only and reserved for the OS. Use Homebrew, pyenv, or
uv python installto get a writable interpreter, then create a venv from there.
References
- PyPA Packaging User Guide — the authoritative tutorial on virtual environments, pip, and pyproject.toml.
- Python docs: venv module — official reference for the standard-library virtual environment tool.
- Poetry documentation — install, add/update dependencies, lockfile semantics, and publishing.
- uv documentation (Astral) — Rust-based installer and resolver with built-in Python and project management.
- pyenv README — installation, shim mechanics, and per-project version selection.
- conda documentation — environment management for Python plus compiled C/Fortran/CUDA dependencies.
Which Python Environment Tool Should You Pick?
- • Always use a virtual environment — never install packages into the system Python
- • venv + pip is the zero-dependency default; use it for simple projects and scripts
- • Poetry adds proper dependency resolution and lock files — ideal for applications and libraries
- • uv is the fastest modern option (10–100× faster than pip) and replaces venv + pip + Poetry + pyenv in one binary — preferred for new apps and monorepos
- • conda is necessary when your stack includes compiled C/Fortran/CUDA dependencies
- • pyenv complements any tool above when you need multiple Python versions on one machine
- • Pin exact versions in production; use compatible-release specifiers (
~=) or caret (^) in libraries - • Keep the syntax handy with the Python cheatsheet for quick reference inside any environment.