Appearance
Python Package Managers
Every Python project eventually needs a library you did not write. A package manager is the tool that fetches that library, figures out which version of it works with your other dependencies, and installs it into your environment. The Python ecosystem has several options. For this course we use uv, which is faster than every alternative and simple enough that you will rarely think about it beyond a handful of commands.
What you'll learn
uv addinstalls a package and writes it topyproject.toml-- one command, declarative, reproducibleuv syncreplays the lockfile: anyone cloning your project gets the exact same dependency tree- You will still see
pip installin tutorials everywhere -- know what it does, but useuvin your own projects
The problem
You find a tutorial that says pip install openai. You run it, and it works. A week later you run pip install langchain, and suddenly openai stops working because langchain pulled in a conflicting version of a shared dependency. pip installs whatever it resolves in the moment. There is no record of exactly which versions were installed, and no way to recreate that exact state on another machine.
Package managers solve this by recording your dependencies and their resolved versions in a file. Anyone who clones your project runs a single command and gets the identical set of packages you had.
Options & when to use each
| Tool | What it does | When to use it |
|---|---|---|
pip | Installs packages from PyPI with no lockfile | Following tutorials, quick one-offs where reproducibility does not matter |
uv | Installs, resolves, and locks dependencies; manages environments | Any project you intend to keep or share -- the default for this course |
| Poetry | Dependency management with a declarative pyproject.toml and lockfile | Teams already standardized on Poetry; functionally similar to uv but slower |
uv is the tool we teach because it does everything pip does, faster, and adds the lockfile workflow that prevents the "it worked last week" problem. It also manages environments (uv venv) and can install Python itself (uv python install). One tool for the entire dependency lifecycle.
Build it
Install a package
With an active virtual environment (see the previous lesson):
bash
# Install a package and record it in pyproject.toml
uv add httpx
# Install multiple packages at once
uv add pydantic openai python-dotenv
# Install a specific version
uv add fastapi==0.115.0After each uv add, two things happen: the package is installed into your .venv, and it is written to pyproject.toml under [project.dependencies]. Check the file after running a few adds:
bash
cat pyproject.tomlYou will see entries like:
toml
[project]
dependencies = [
"httpx>=0.28.0",
"pydantic>=2.0",
"openai>=1.0",
]The lockfile
Every time you run uv add or uv lock, uv creates or updates uv.lock. This file records the exact version of every package and every transitive dependency (the dependencies of your dependencies). It is the guarantee that your project builds identically on every machine.
bash
# Create or update the lockfile from pyproject.toml
uv lock
# Install everything exactly as specified in the lockfile
uv syncCommit uv.lock to version control. Do not commit .venv/. When someone clones your project:
bash
git clone https://github.com/you/my-agent-project
cd my-agent-project
uv sync
# .venv is created, all dependencies installed, identical to yoursRemoving a package
bash
uv remove httpx
# Removes from pyproject.toml and from the environmentWhat you will see in tutorials: pip
Most tutorials outside this portal use pip. When you see pip install openai, translate it mentally: pip puts packages into whichever environment is active, same as uv add, but pip does not update pyproject.toml. If you are inside a uv-managed project and want to use pip for a one-off:
bash
# Inside an activated uv environment, pip installs to .venv
source .venv/bin/activate
pip install some-experimental-package
# Package is installed, but NOT recorded in pyproject.tomlIf you decide to keep that package, add it properly afterward:
bash
uv add some-experimental-packageExporting to requirements.txt
Some deployment systems still expect a requirements.txt file. uv can generate one:
bash
uv pip compile pyproject.toml -o requirements.txtThis produces a pinned requirements.txt from your pyproject.toml dependencies.
What goes wrong
| Mistake | How you notice it | The fix |
|---|---|---|
Used pip install instead of uv add | Package works but does not appear in pyproject.toml | Run uv add <package> to record it properly |
Forgot to run uv sync after pulling | ModuleNotFoundError on a package your teammate added | Run uv sync. It installs everything from the lockfile |
uv.lock merge conflict | Git shows a conflict in uv.lock after merging a branch | Delete uv.lock, run uv lock, commit the regenerated file. uv.lock is machine-generated, do not hand-edit it |
| Cache taking up disk space | uv cache dir shows gigabytes used | Run uv cache clean. The cache speeds up installs but grows over time. Cleaning it is safe -- packages re-download when needed |
| Installed a package globally (outside an environment) | uv add fails with permissions errors | Never run uv add or pip install without an active environment. If you see a permission error, activate the environment first |
Confirm it worked
After setting up a project with dependencies, verify everything is reproducible:
bash
# 1. Check that pyproject.toml lists your dependencies
grep -A 5 "dependencies" pyproject.toml
# Should show the packages you added
# 2. Check that the lockfile exists and is recent
ls -lh uv.lock
# Should exist and have a timestamp matching your last uv add or uv lock
# 3. Simulate a fresh install
rm -rf .venv
uv sync
# Should recreate .venv and install all packages from scratch in seconds
# 4. Verify your code still runs
python -c "import httpx; print(httpx.__version__)"
# Should print the installed version without errorsNext: Git & Version Control