-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
166: Introduction to uv for Fast Dependency Management
A few years ago, I was working on a data pipeline project that relied on a fairly heavy stack—Pandas, Scikit-learn, and a handful of specialized API wrappers. Every time a new developer joined the team, or we spun up a fresh CI/CD runner, we'd hit the same bottleneck: pip install -r requirements.txt. It would sit there, chewing through CPU and network, taking a solid five to seven minutes just to resolve dependencies and download packages. It sounds like a small annoyance, but when you're iterating quickly, those minutes add up to a lot of wasted mental energy. I remember thinking there had to be a better way than just "waiting for the wheel to turn."
Enter uv. Developed by Astral (the same folks who gave us Ruff), uv is an extremely fast Python package installer and resolver written in Rust. It isn't just a slightly faster version of pip; it's designed to be a drop-in replacement that fundamentally changes the speed of your workflow. In most cases, it's an order of magnitude faster because it leverages a global cache and a highly optimized resolution engine.
Getting the Rust-Powered Speed Boost
The beauty of uv is that it doesn't try to force you into a completely new paradigm immediately. It provides a uv pip interface that mimics the commands you already know. If you're used to pip install, you'll feel right at home, just with a massive performance jump. (Seriously, the first time you run it, it feels like a bug because it finishes so quickly.)
To get started, you install uv as a standalone binary. Once it's on your system, you can create a virtual environment almost instantaneously. Instead of the slow python -m venv .venv, you use:
uv venv
This creates a standard .venv directory, but it does so in a fraction of the time. From there, you can install your packages using the uv pip command. For example, if you're building a tool that needs httpx and pydantic, you'd run:
uv pip install httpx pydantic
Replacing the Pip-Tools Workflow
If you've done professional Python work, you know that requirements.txt is often too loose for production. You want a "lockfile"—a file that specifies the exact version of every single sub-dependency to ensure that what works on your machine is exactly what runs in production. Traditionally, we used pip-tools for this, but uv has this functionality baked right in.
I typically maintain a requirements.in file where I list only my top-level dependencies (the ones I actually care about). Then, I use uv pip compile to generate the fully pinned requirements.txt:
uv pip compile requirements.in -o requirements.txt
Once you have that lockfile, you don't want to just "install" it; you want your environment to match that file exactly. This is where uv pip sync comes in. Unlike pip install, which just adds packages, sync will actually uninstall anything in your environment that isn't in the lockfile. This prevents "dependency drift," where your local environment has random packages installed that your teammates don't have, leading to the dreaded "it works on my machine" syndrome.
📋 Practical Task
Exercise: Migrating a Heavy Dependency Set to uv
In this exercise, you will simulate migrating a project from a standard pip workflow to a uv workflow to experience the speed and locking benefits.
Requirements: Install uv on your system before starting.
- Create a new directory for this project and navigate into it.
- Create a file named
requirements.inand add the following three libraries:requestsrichpandas
- Initialize a virtual environment using
uv venv. - Activate the environment (
source .venv/bin/activateon macOS/Linux or.venv\Scripts\activateon Windows). - Use
uv pip compileto transform yourrequirements.ininto a pinnedrequirements.txt. - Use
uv pip syncto synchronize your environment with the newly createdrequirements.txt. - Verify the installation by running a quick one-liner to import the libraries:
python -c "import requests, rich, pandas; print('Success!')".
There are no comments for now.