Where does the install go?
After this you can set up a clean Python for any lab, and you always know which Python runs your code.
Which Python is this?
Guess first Your laptop holds two Pythons. You type python3. Which one runs?
On Windows, run this chapter in WSL 2, Microsoft's Linux inside Windows, and type each command there.
In chapter 1 you typed python3. Your shell runs the first python3 it finds on your PATH, and a laptop can hold several Pythons.
Ask Python: sys.version is its version. sys.executable is its interpreter's path. Lesson 2 explains the tag below.
On a Mac, /usr/bin/python3 is Apple's Python. Apple's own tools need it, and it is usually older: leave it alone.
Common mistake: any Python 3 runs the labs. With Python 3.9, pip quietly installs torch 2.8.0, the last release that accepts 3.9.
Why: each release on PyPI, Python's package registry, lists the Pythons it accepts. pip skips every release that refuses yours.
Pick one version every lab package accepts: numpy needs 3.12 or newer, and vLLM 0.31 is tested on 3.10 to 3.13. We use 3.13.
First, install uv, a free tool that installs Pythons.
Run it: uv python install 3.13 puts Python 3.13 beside your other Pythons. Its command is python3.13.
Quick check You run python3 -m pip install torch and get torch 2.8.0, with no error. What happened?
One Python per project: the venv
Guess first In a new, empty project folder you run pip install httpx. pip is Python's installer, and httpx is an HTTP package. Where does httpx go?
Guess first Two projects share one Python. One needs httpx 0.27, the other httpx 0.28. You install both. What happens?
pip installs into the Python that runs it, not into your project. npm installs into ./node_modules, inside your project.
One Python's site-packages holds one version of each package: httpx 0.28 replaces 0.27. npm can nest both.
venv_demo.py makes a throwaway venv, then installs a tiny package, demo-pkg, at 1.0 and then at 2.0, offline.
Run it: pip removes demo-pkg 1.0 before it installs 2.0. site-packages ends with one version.
Python's answer is a virtual environment (venv): one folder per project, with a link to one Python and its own site-packages.
At work, give each engine its own venv too. vLLM wants a fresh one: its compiled code is built for one PyTorch version.
Run it: make one. python3.13 -m venv .venv builds the folder, with its own bin, lib and a pyvenv.cfg.
Activating (source .venv/bin/activate) puts .venv/bin first on PATH, like nvm use. You can skip it and run .venv/bin/python directly.
Run it: after source .venv/bin/activate, which python3 finds the venv's Python. Without activating, .venv/bin/python still runs it.
Never commit .venv or copy it elsewhere: it holds absolute paths. Delete and rebuild it instead. Since 3.13 it even tells git to ignore it.
Run it: cat .venv/.gitignore shows what keeps the folder out of git.
A common wall: some Pythons, like Homebrew's, refuse pip installs to protect the system. Fix it with a venv, never --break-system-packages.
Run it: ask Homebrew's python3 to install into itself. It refuses, and its error suggests a venv.
Quick check pip install httpx prints error: externally-managed-environment. What is the smallest safe fix?
Quick check You made .venv but did not activate it. Which command installs httpx into the venv?
Lockfiles, and uv
Guess first You add a package by hand to pyproject.toml (Python's package.json), then run uv sync --frozen. Is the new package installed?
uv also manages projects, like npm. uv init --python 3.13 bridge starts one in a new folder. Later labs install their packages with uv.
The files map one to one: pyproject.toml is package.json, the lockfile uv.lock is package-lock.json, .venv is node_modules, .python-version is .nvmrc.
Run it: uv add httpx installs httpx, and the packages it needs, into the project's .venv, like npm install ws.
uv add httpx saves httpx>=0.28.1: any newer version. npm's ^8.18.0 stops below 9.0.0. Only the lockfile pins exact versions.
uv sync --locked acts like npm ci: when the lockfile is out of date, it stops with an error. CI should use --locked.
uv sync --frozen skips that check. It installs from the old lockfile, with no error and no warning, so the new package is missing.
Quick check A CI job must install exactly what uv.lock says, and fail loudly if someone forgot to update it. Which command?
Quick check Put the steps in order to set up a new lab on a fresh laptop.
Notebooks: the first cell
Guess first A notebook is a page of code cells you run one at a time. Cell 2 sets x = 1, and you ran it. You restart the notebook, then run only cell 3: print(x + 1). What happens?
Later labs on free GPUs use notebooks; this chapter needs none. Notebooks break easily: of 863,878 runs of GitHub notebooks, 24% had no error.
Every notebook lab starts with cell 1, our env_check.py: it prints the Python, its path and venv status, then stops on a wrong version.
Run it: in the lab venv the check passes. Apple's Python 3.9 is outside 3.12 to 3.14, so it stops with a plain message.
In a notebook, install with %pip install ...: it runs pip with the kernel's own Python. !pip asks your shell, and PATH may pick another.
Cells run out of order hide old values. Restart the kernel and run every cell before you trust a number.
Quick check Yesterday your notebook ran fine. Today you open it and run cell 7 first. It raises NameError. What is the most likely cause?
Quick check In a notebook you run !pip install httpx. Then import httpx fails with ModuleNotFoundError. What happened?