The AI engineer track, and dev environments with uv
Installing Python, why uv instead of pip, and an isolated, reproducible environment for every project with uv init, uv add and uv run — plus the right interpreter in your editor.
How do you want to learn?
The problem we are solving
A new AI engineer joins a team. The first day's task is simple: get the project running on their own laptop. The README says "run python main.py". They run it and get ModuleNotFoundError: No module named 'httpx'. On the machine of the person who wrote the project, the same command works perfectly.
Digging in, it turns out that for two years every package every project on the author's machine ever needed has been piling up in the same Python. Which packages this project depends on is written down nowhere — only "it works on my machine". The new colleague spends half a day finding and installing packages one at a time, and at the end one of them is a different version, so the results differ too.
Professional teams have one answer to this: every project gets its own isolated environment, and what that environment contains is written in a file, so anyone can build exactly the same environment with one command. That is what we build in this chapter — with uv — and it is what we use for the rest of the course.
By the end of this chapter you can
- Install Python both with the normal installer and with
uv python install, and say how the two differ - Explain what
pipis and why this course usesuvinstead - Create and run an isolated project environment with
uv init,uv add,uv runanduv venv - Show with an example why projects should not run on the system Python
- Select the project's own interpreter in VS Code or PyCharm
Prerequisites: changing folders in a terminal (cd) and running a command. This is the first chapter of the course, so nothing else is needed.
How this track works
This course is a career track. Each chapter is like one class, and each ends with a task to run on your own machine. The early chapters lay the foundation of professional work — environments, Git, project structure, configuration. After that come clean Python, testing, APIs, databases, RAG, security and deployment.
One thing is worth saying up front: at a company, an AI engineer's code is not accepted just because it "runs". Whether someone else can run it on their machine, whether someone can review it, whether anyone will understand it six months from now — those are part of the job too. So every hands-on task in this course is set up as if it were going into a real team's repository. And the first step of that habit is the environment.
Installing Python: two routes
Route one — the normal installer. Download the 3.12 installer from python.org and run it. On Windows, tick Add python.exe to PATH on the very first screen; without it the terminal will not recognise the python command. On macOS, running the .pkg from python.org is enough. On Linux, python3 is usually there already — and there is a warning about that below.
To check:
python --version
Python 3.12.0On macOS and Linux the command is often python3 --version.
Route two — with uv. uv is a single tool that handles Python versions, project environments and packages. Install uv first. On macOS and Linux:
curl -LsSf https://astral.sh/uv/install.sh | shIn Windows PowerShell:
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"Then open a new terminal:
uv --version
uv 0.9.1 (9887ef5bd 2025-10-09)Your version number may differ. Now Python:
uv python install 3.12
Installed Python 3.12.11 in 27.42s
+ cpython-3.12.11-windows-x86_64-none (python3.12.exe)The time and the platform name at the end will be different on your machine. Notice that the Python uv installed lives in a folder of its own — it does not touch the machine's main Python, and it does not change PATH.
The two routes can coexist, and both work for this course. The difference: the normal installer gives you one Python for the whole computer; uv python install gives you Pythons that projects pick as they need. One project wants 3.12, another 3.13 — neither gets in the other's way.
What pip is, and why we use uv
Python's outside packages — httpx, pydantic, fastapi — live in a repository called PyPI. The traditional tool for fetching them is pip, which comes with Python. Nearly every tutorial on the internet says pip install ....
pip works well, but it does one job only: installing packages. And it installs them into whichever Python it was run with. For a professional project, everything else needed a separate tool:
- getting the right Python version — a separate tool
- creating and activating an isolated environment —
python -m venv, thenactivateby hand - recording what the project needs — by hand, in a file, often forgotten
- pinning exactly which version of every package was used (a lockfile) — yet another tool
uv does all four in one tool, and does them much faster. Most importantly, when you add something with uv add, it is written into the project's file automatically. "I installed it but forgot to write it down" — the root cause of the new colleague's trouble above — cannot happen this way.
So wherever packages or environments come up in this course, it is uv. When you see pip install somewhere else, the uv equivalent is almost always uv add.
Why the system Python is not the place for projects
The "system Python" is the Python installed directly on the computer — the one that runs when you type python in a terminal without activating any environment. Installing a project's packages into it causes three problems:
- Everyone shares one room. One project needs
pydantic1, another needs 2. The system Python can hold only one, so fixing one project breaks the other. - Dependencies become invisible. The package was already installed for some old project, so the new project runs — yet nowhere in the project does it say it needs that package. No error appears on your machine; the error appears on a colleague's machine, or on the server.
- The operating system uses it. On macOS and Linux, some system tools run on that Python. Changing its packages can break them — which is why recent Linux releases block installing into the system Python directly.
The second problem is the most dangerous because it is silent. The system Python on the machine this chapter was written on still has httpx, pydantic and rich left over from old work. So any script "runs" there — and that is exactly why there is no way to tell from it what a script really needs.
The mistaken belief is: "It runs on my machine, so it's fine." A script that runs on the system Python only proves that at some point the package was installed on your machine. What the project itself needs is proven only when everything is installed into an empty environment from the project's own file, and then the script runs.
A first project with uv
Standing in a work folder:
uv init hello-ai --python 3.12
Initialized project `hello-ai` at `D:\ai-lab\hello-ai`(The path at the end will be your own folder; transcripts in this chapter shorten paths.) uv init creates a new folder, and inside it:
hello-ai/
├── .git/
├── .gitignore
├── .python-version
├── README.md
├── main.py
└── pyproject.tomlThe most important of these is pyproject.toml — the project's identity card:
[project]
name = "hello-ai"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []dependencies = [] — the project does not need any outside package yet. .python-version contains just 3.12: which Python this project runs on. And uv init has created a Git repository and a .gitignore for you — they come into play in the next chapter.
Now run it:
cd hello-ai
uv run main.py
Using CPython 3.12.11
Creating virtual environment at: .venv
Hello from hello-ai!The first time, uv run created a .venv folder on its own — that is the project's isolated environment — and then ran main.py with that environment's Python. You did not have to activate anything.
uv add: adding a package, and writing it down
Almost every project an AI engineer works on calls some API, so the first package is the HTTP client httpx, plus python-dotenv for reading .env files:
uv add httpx python-dotenv
Resolved 9 packages in 119ms
Installed 8 packages in 92ms
+ anyio==4.15.1
+ certifi==2026.7.22
+ h11==0.16.0
+ httpcore==1.0.9
+ httpx==0.28.1
+ idna==3.20
+ python-dotenv==1.2.3
+ typing-extensions==4.16.0You asked for two packages and got eight — the rest are httpx's own dependencies, which uv worked out by itself. The version numbers may be newer when you do this.
Now look at pyproject.toml:
[project]
name = "hello-ai"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"httpx>=0.28.1",
"python-dotenv>=1.2.3",
]One command did three things: the packages were installed into .venv, pyproject.toml now records that the project needs them, and a new file called uv.lock appeared, pinning the exact version of all eight packages. Lockfiles get a proper discussion a little later in the course; for now it is enough to know that a colleague who clones the repository and runs uv sync gets exactly these eight versions.
To take something out, uv remove:
uv remove python-dotenv
Resolved 8 packages in 21ms
Uninstalled 1 package in 11ms
- python-dotenv==1.2.3This also works in both places: it removes the package from .venv and deletes it from pyproject.toml.
uv venv, and activating by hand
uv run creates and uses the environment for you, so in this course it is almost always enough. Sometimes, though, you just need an empty environment — for example in an old project that has no pyproject.toml yet. Then:
uv venv --python 3.12
Using CPython 3.12.11
Creating virtual environment at: .venv
Activate with: .venv\Scripts\activateThat last line is from Windows PowerShell. This is where operating systems differ:
# Windows (PowerShell)
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activateOnce active, the prompt starts with (hello-ai) or (.venv), and a plain python command runs that environment's Python. To leave, deactivate. Remember that with uv run none of this is needed — that is its advantage, and writing uv run in a team README is the safe choice, because there is no such state as "forgot to activate".
Pointing the editor at the project's Python
The program runs in the terminal, yet the editor shows a red underline under import httpx — this almost always means the editor is looking at a different Python.
VS Code: install Microsoft's Python extension. Then open the project folder, press Ctrl + Shift + P (Cmd + Shift + P on macOS) → Python: Select Interpreter → pick the Python inside .venv. If it is not listed, use Enter interpreter path and point to it: .venv\Scripts\python.exe on Windows, .venv/bin/python on macOS/Linux.
PyCharm: Settings → Project → Python Interpreter → Add Interpreter → Add Local Interpreter → choose an existing environment and give the same path. Recent versions also offer a uv environment type directly.
The easy way to be sure which Python the editor is using is to run this in the editor's built-in terminal:
import sys
print(sys.executable)The path should end inside your project's .venv — for example ...\hello-ai\.venv\Scripts\python.exe. The start of the path depends on your folder, so the full output is not shown here.
A complete example
In the hello-ai project, create a file called env_check.py. It is a small "environment check" script — when someone new joins a team, running something like this first confirms that everything is where it should be:
import sys
from importlib.metadata import version
from pathlib import Path
def main() -> None:
in_venv = sys.prefix != sys.base_prefix
print(f"Python : {sys.version_info.major}.{sys.version_info.minor}")
print(f"In a venv : {in_venv}")
print(f"Env folder : {Path(sys.prefix).name}")
import httpx # installed with `uv add httpx`
print(f"httpx : {version('httpx')}")
print(f"Client ready: {httpx.Client is not None}")
print("Hello, AI engineer.")
if __name__ == "__main__":
main()Run it from inside the project:
uv run env_check.pyPython : 3.12
In a venv : True
Env folder : .venv
httpx : 0.28.1
Client ready: True
Hello, AI engineer.Now let us run the same file in an empty environment. The file was copied into another folder, an environment was created there with uv venv --python 3.12, and the file was run directly with that environment's Python (.venv\Scripts\python env_check.py on Windows, .venv/bin/python env_check.py on macOS/Linux):
Python : 3.12
In a venv : True
Env folder : .venv
Traceback (most recent call last):
File "env_check.py", line 20, in <module>
main()
File "env_check.py", line 12, in main
import httpx # installed with `uv add httpx`
^^^^^^^^^^^^
ModuleNotFoundError: No module named 'httpx'(On your machine the traceback shows the file's full path; only the name is kept here.)
A few decisions in this script are worth noticing.
sys.prefix != sys.base_prefix — Python itself knows whether it is running in a virtual environment. sys.base_prefix is the base Python the environment was created from, and sys.prefix is the one running now. If they differ, you are inside an environment.
The folder name, not the full path — Path(sys.prefix).name prints only the last part, .venv. The full path is different on every machine; the name is the same for everyone. The less machine-specific a check script's output is, the easier it is to compare in the team chat.
import httpx in the middle of the function — imports normally go at the top of a file, and should. Here it is deliberately placed in the middle, so that in an empty environment the first three lines print before the error. The error output then tells its own story: Python 3.12 is fine, an environment is active, but that environment has no httpx. The fix is uv add httpx — or, if the project's pyproject.toml already lists it, uv sync.
version('httpx') — importlib.metadata is the standard way to read a package's version. Not every package has a __version__, but every installed package has metadata.
When it breaks
The term 'uv' is not recognized as the name of a cmdlet, function, script file, or operable program (on macOS/Linux, uv: command not found) uv is installed, but the terminal you are typing in was opened before the install, so it does not know the new PATH. Close and reopen the terminal (and, in VS Code, the whole editor).
error: No pyproject.toml found in current directory or any parent directory You ran uv add outside a project folder. uv add writes to the project's file, so with no project there is nowhere to write. cd into the project, or run uv init first if it is new.
ModuleNotFoundError: No module named 'httpx' The Python running the script does not have the package. Two usual causes: the package was never added with uv add, or the script was run with plain python instead of uv run, so the system Python ran instead of the project's environment. Run it with uv run env_check.py.
error: Failed to spawn: hello.py followed by Caused by: program not found You gave uv run a file name that is not in the current folder — usually a spelling mistake, or you are in the wrong folder. Not finding a file, uv looked for a program by that name instead, which is why the message reads oddly.
× No solution found when resolving dependencies followed by Because htpx was not found in the package registry ... A typo in the package name (htpx). The good news is that a failed uv add changes nothing — pyproject.toml and uv.lock stay as they were. Fix the spelling and run it again.
.venv\Scripts\activate : File ... cannot be loaded because running scripts is disabled on this system A PowerShell security policy. Run Set-ExecutionPolicy -Scope CurrentUser RemoteSigned once and open a new terminal — or skip activation and run everything with uv run.
Step 4 of 6 — Predict
Check your understanding
This file is saved as check.py in the hello-ai project and run with uv run check.py. What prints?
import sys
print(sys.prefix != sys.base_prefix)
print(sys.version_info.major)- A`.venv`, then `3.12`
- B`True`, then `3`
- C`True`, then `12`
- D`False`, then `3`
The project's pyproject.toml lists httpx, and uv.lock is in the repository. Still, a new colleague following the README on a brand-new laptop gets ModuleNotFoundError: No module named 'httpx'. Where is the bug in the README?
# README of a team project, "How to run" section:
# 1. git clone <repo-url>
# 2. cd summarizer
# 3. python main.py
import httpx
print("client:", httpx.Client.__name__)- AA step running `uv init` after the clone is missing
- BThe colleague must first run `uv add httpx`, then `python main.py`
- CThe `import httpx` line must move from the top of the file into a `main()` function
- DStep 3 runs the system Python; it should say `uv run main.py`, which builds `.venv` from `pyproject.toml` and `uv.lock` and runs inside it
After uv init and uv add, the project has pyproject.toml, uv.lock, .python-version and .venv. Which of these go into the team's Git repository?
- AEverything except `.python-version`, since the Python version is a personal choice
- B`pyproject.toml`, `uv.lock` and `.python-version` go in; `.venv` does not
- CAll four, including `.venv`, so colleagues do not have to install anything
- DOnly `pyproject.toml`; `uv.lock` is generated, so leave it out too
Play is part of Pro
+30 XP waiting
Play this chapter with Pro
Reading is free, and the whole chapter is open. The first 5 chapters of every free course are free to play. From chapter 6, answering the questions, earning XP and growing your streak is part of Pro.
Unlock Play with ProYour turn
With uv and Python 3.12 ready on your machine, create a new project:
- Create the project with
uv init my-first-agent --python 3.12, and add one package withuv add httpx - Write the
env_check.pyfile above into the project exactly, and run it withuv run env_check.py - Open
pyproject.tomland show thathttpxis listed underdependencies, and that auv.lockfile was created in the project - Open the project in VS Code or PyCharm and select the project's
.venvas the interpreter, so there is no red underline on theimport httpxline
Expected output (the httpx version may be newer when you do this):
Python : 3.12
In a venv : True
Env folder : .venv
httpx : 0.28.1
Client ready: True
Hello, AI engineer.Then break it on purpose: run uv remove httpx and run uv run env_check.py again. Write down how far it prints, which error appears, and what changed in pyproject.toml. Then fix it with uv add httpx. This break-and-repair loop takes two minutes, but in the first week of your first job it is the thing that will save you the most time.
Step 6 of 6
Stretch — the chapter quiz
Ten questions from easy to hard. The last ones are difficult on purpose.
Play with Pro