Setting Up a Modern Python Environment with uv
A practical guide to setting up a fast, reproducible Python development environment using uv : the Rust-based package manager that replaces pip, virtualenv, and pyenv.
Why uv?
If you have been using Python for machine learning, you have probably dealt with the pain of managing virtual environments, slow pip installs, and version conflicts. uv solves all of this.
uv is a Rust-based Python package manager that is 10-100x faster than pip. It handles virtual environments, Python version management, and dependency resolution in a single tool.
Key Takeaway
uv replaces pip, virtualenv, pyenv, and pip-tools with a single, blazing-fast tool.
Installing uv
The fastest way to install uv on macOS or Linux:
curl -LsSf https://astral.sh/uv/install.sh | shOn Windows:
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"Verify the installation:
uv --versionCreating a New Project
uv has a built-in project scaffolding command:
uv init my-ml-project
cd my-ml-projectThis creates a clean project structure:
my-ml-project/
├── .python-version
├── pyproject.toml
├── README.md
└── src/
└── my_ml_project/
└── __init__.pyManaging Python Versions
One of the best features of uv is built-in Python version management. No more pyenv:
# Install a specific Python version
uv python install 3.12
# Pin the project to a specific version
uv python pin 3.12
# List available versions
uv python listAutomatic Downloads
uv automatically downloads the correct Python version when you run commands. You do not need to pre-install Python.
Adding Dependencies
Adding packages is fast and simple:
# Add a package
uv add numpy pandas scikit-learn
# Add a dev dependency
uv add --dev pytest ruff mypy
# Add with version constraints
uv add "torch>=2.0"uv generates a uv.lock lockfile for reproducible installs : similar to package-lock.json in Node.js.
Virtual Environments
uv manages virtual environments automatically. When you run uv add or uv sync, it creates a .venv in your project root:
# Sync all dependencies from pyproject.toml
uv sync
# Run a command inside the virtual environment
uv run python train.py
# Run pytest
uv run pytestNo Manual Activation Needed
You do not need to activate the virtual environment. Use uv run to execute commands within it. This ensures reproducibility.
Best Practices for ML Projects
Here is a recommended pyproject.toml for an ML project:
[project]
name = "my-ml-project"
version = "0.1.0"
description = "A machine learning project"
requires-python = ">=3.11"
dependencies = [
"numpy>=1.26",
"pandas>=2.0",
"scikit-learn>=1.4",
"matplotlib>=3.8",
]
[dependency-groups]
dev = [
"pytest>=8.0",
"ruff>=0.3",
"mypy>=1.8",
"jupyter>=1.0",
]
[tool.ruff]
line-length = 88
target-version = "py311"
[tool.mypy]
python_version = "3.11"
strict = trueTips
- Always use
uv.lock: commit it to version control for reproducible builds - Separate dev dependencies : use dependency groups to keep production lean
- Pin Python version : use
.python-versionfile for consistency across machines - Use
uv run: avoid activating venvs manually for cleaner workflows
Comparing uv to Traditional Tools
| Feature | pip + venv | uv |
|---|---|---|
| Install speed | Slow | 10-100x faster |
| Lockfile | No (needs pip-tools) | Built-in |
| Python management | No (needs pyenv) | Built-in |
| Dependency resolution | Basic | Advanced (PubGrub) |
| Single tool | No | Yes |
Conclusion
uv is the modern way to manage Python environments for ML projects. It is fast, reproducible, and eliminates the need for multiple tools. If you are starting a new project, there is no reason not to use it.