C.W.K.
Stream
Lesson 03 of 05 · published

Virtual Environments — venv, uv, and the Modern Setup

~18 min · venv, virtualenv, uv, isolation

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete

Why virtualenvs exist

Without isolation, every pip install goes into the system Python. Two projects that need different versions of the same library can't coexist. Virtual environments give each project its own isolated site-packages directory — install whatever you want, no conflicts.

venv — the stdlib answer

python -m venv .venv creates a virtualenv in .venv/. Activate with source .venv/bin/activate (Unix) or .venv\Scripts\activate (Windows). After activation, python and pip point at the venv's binaries. Deactivate with deactivate. This is the standard, ships with Python, and works everywhere.

uv — the modern fast alternative

uv (from Astral) is a Rust-written drop-in for pip + venv that's 10-100x faster. uv venv creates an env. uv pip install foo installs into it. Pippa's stack uses uv. The tradeoff: it's still maturing relative to pip, and pip is the universally available baseline. Use uv when you can; fall back to pip when you can't.

conda — separate ecosystem

conda manages both Python interpreters and packages, and supports non-Python dependencies (CUDA, BLAS, system libraries). Useful for data science, ML, anywhere you need pre-built binaries with system-level deps. Pippa runs in a conda env (cwk-pippa) for exactly this reason. Use conda when you need it; use venv/uv when you don't.

Principle: One venv per project. Never pip install into system Python. The cost of activation is ~1 second; the cost of dependency hell from skipping it is hours.

Code

venv — the standard way·bash
# Create a venv in the current directory
python -m venv .venv

# Activate (Unix/macOS)
source .venv/bin/activate

# Activate (Windows PowerShell)
# .venv\Scripts\Activate.ps1

# Now pip installs into the venv
pip install requests

# Verify
which python                  # /path/to/.venv/bin/python
which pip                     # /path/to/.venv/bin/pip

# Deactivate when done
deactivate
uv — modern, fast·bash
# Install uv (one-time, system level)
# curl -LsSf https://astral.sh/uv/install.sh | sh

# Create a venv
uv venv .venv

# Activate (same as venv)
source .venv/bin/activate

# Install — uv pip is dramatically faster
uv pip install requests httpx

# Or use uv's project mode (no separate venv activation needed)
# uv add requests           — adds to pyproject.toml + .venv
# uv run python script.py    — runs in the project's venv
Inspecting a venv·python
import sys
# Inside an activated venv:
print(sys.prefix)             # /path/to/.venv
print(sys.executable)         # /path/to/.venv/bin/python

# Sometimes useful — distinguish base interpreter from venv
print(sys.base_prefix)        # /path/to/system/python
print(sys.prefix == sys.base_prefix)   # False if in venv, True if not
Direnv — auto-activate per directory·bash
# direnv (separate tool, brew install direnv) loads .envrc when you cd in.
# In a project directory:
# echo "source .venv/bin/activate" > .envrc
# direnv allow
#
# Now cd-ing into the directory auto-activates the venv,
# and cd-ing out deactivates.
#
# Pippa uses direnv with conda — cd into cwkPippa
# and the cwk-pippa conda env activates automatically.

External links

Exercise

Create a fresh venv in /tmp/test_venv using python -m venv. Activate it. Confirm which python points there. Install one package (e.g., requests) and verify it's in /tmp/test_venv/lib/python3.x/site-packages/. Deactivate. Confirm which python no longer points to the venv. Then delete the directory.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.