Il percorso per AI engineer e gli ambienti di sviluppo con uv
Installare Python, perché uv al posto di pip, e un ambiente isolato e riproducibile per ogni progetto con uv init, uv add e uv run — più l'interprete giusto nel tuo editor.
Come vuoi imparare?
Il problema che stiamo risolvendo
Un nuovo AI engineer entra in un team. Il compito del primo giorno è semplice: far partire il progetto sul proprio portatile. Il README dice "esegui python main.py". La persona esegue il comando e ottiene ModuleNotFoundError: No module named 'httpx'. Sulla macchina di chi ha scritto il progetto, lo stesso comando funziona perfettamente.
Indagando, si scopre che per due anni, sulla macchina dell'autore, tutti i pacchetti di ogni progetto si sono accumulati nello stesso Python. Da nessuna parte è scritto di quali pacchetti abbia bisogno questo progetto — c'è solo "funziona sulla mia macchina". Il nuovo collega passa mezza giornata a cercare e installare i pacchetti uno alla volta, e alla fine uno è di una versione diversa, quindi cambiano anche i risultati.
I team professionali hanno una sola risposta: ogni progetto ottiene il proprio ambiente isolato, e ciò che quell'ambiente contiene è scritto in un file, così chiunque può ricreare esattamente lo stesso ambiente con un solo comando. È quello che costruiamo in questo capitolo — con uv — ed è quello che usiamo per il resto del corso.
Alla fine di questo capitolo sarai in grado di
- Installare Python sia con il normale installer sia con
uv python install, e spiegare in cosa differiscono - Spiegare cos'è
pipe perché questo corso usauval suo posto - Creare ed eseguire un ambiente isolato di progetto con
uv init,uv add,uv runeuv venv - Mostrare con un esempio perché i progetti non dovrebbero girare sul Python di sistema
- Selezionare l'interprete del progetto in VS Code o PyCharm
Cosa ti serve prima: cambiare cartella nel terminale (cd) e lanciare un comando. Questo è il primo capitolo del corso, quindi non serve altro.
Come funziona questo percorso
Questo corso è un percorso di carriera. Ogni capitolo è come una lezione, e ognuno si chiude con un compito da eseguire sulla tua macchina. I primi capitoli gettano le basi del lavoro professionale — ambienti, Git, struttura dei progetti, configurazione. Poi vengono Python pulito, test, API, database, RAG, sicurezza e deployment.
Una cosa va detta subito: in azienda il codice di un AI engineer non viene accettato solo perché "funziona". Che un altro possa eseguirlo sulla sua macchina, che qualcuno possa rivederlo, che qualcuno lo capisca tra sei mesi — anche questo fa parte del lavoro. Per questo ogni compito pratico del corso è impostato come se finisse nel repository di un vero team. E il primo passo di questa abitudine è l'ambiente.
Installare Python: due strade
Prima strada — l'installer normale. Scarica l'installer 3.12 da python.org ed eseguilo. Su Windows, spunta Add python.exe to PATH già dalla prima schermata; senza, il terminale non riconoscerà il comando python. Su macOS basta aprire il .pkg di python.org. Su Linux, python3 di solito c'è già — e più sotto c'è un avvertimento su questo.
Per verificare:
python --version
Python 3.12.0Su macOS e Linux il comando è spesso python3 --version.
Seconda strada — con uv. uv è un unico strumento che gestisce versioni di Python, ambienti di progetto e pacchetti. Prima installa uv. Su macOS e Linux:
curl -LsSf https://astral.sh/uv/install.sh | shIn Windows PowerShell:
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"Poi apri un terminale nuovo:
uv --version
uv 0.9.1 (9887ef5bd 2025-10-09)La tua versione potrebbe essere diversa. Ora 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)Il tempo e il nome della piattaforma alla fine saranno diversi sulla tua macchina. Nota che il Python installato da uv vive in una cartella tutta sua — non tocca il Python principale della macchina e non cambia il PATH.
Le due strade possono coesistere, e funzionano entrambe per questo corso. La differenza: l'installer normale ti dà un solo Python per tutto il computer; uv python install ti dà Python che i progetti scelgono in base alle esigenze. Un progetto vuole Python 3.12, un altro Python 3.13 — nessuno dei due ostacola l'altro.
Che cos'è pip, e perché usiamo uv
I pacchetti esterni di Python — httpx, pydantic, fastapi — stanno in un repository chiamato PyPI. Lo strumento tradizionale per scaricarli è pip, che viene installato insieme a Python. Quasi ogni tutorial su internet dice pip install ....
pip funziona bene, ma fa un solo lavoro: installare pacchetti. E li installa nel Python con cui viene eseguito. Per un progetto professionale, tutto il resto richiedeva uno strumento separato:
- scegliere la versione giusta di Python — uno strumento a parte
- creare e attivare un ambiente isolato —
python -m venv, poiactivatea mano - registrare di cosa ha bisogno il progetto — a mano, in un file, spesso dimenticato
- fissare esattamente la versione di ogni pacchetto usata (un lockfile) — un altro strumento ancora
uv fa tutti e quattro i compiti in un unico strumento, e li fa molto più in fretta. Soprattutto, quando aggiungi qualcosa con uv add, viene scritto automaticamente nel file del progetto. "L'ho installato ma mi sono dimenticato di scriverlo" — la causa del problema del nuovo collega visto sopra — con questo metodo non può succedere.
Quindi ovunque in questo corso compaiano pacchetti o ambienti, si usa uv. Quando vedi un pip install altrove, l'equivalente con uv è quasi sempre uv add.
Perché il Python di sistema non è il posto per i progetti
Il "Python di sistema" è il Python installato direttamente sul computer — quello che parte quando digiti python in un terminale senza attivare nessun ambiente. Installare i pacchetti di un progetto lì crea tre problemi:
- Tutti condividono una stessa stanza. Un progetto usa
pydantic1, un altro la 2. Il Python di sistema ne può contenere una sola, quindi aggiustare un progetto ne rompe un altro. - Le dipendenze diventano invisibili. Il pacchetto era già installato per qualche vecchio progetto, quindi il nuovo progetto funziona — eppure da nessuna parte del progetto è scritto che ne ha bisogno. Sulla tua macchina non appare nessun errore; l'errore compare sul computer di un collega, o sul server.
- Il sistema operativo lo usa. Su macOS e Linux alcuni strumenti di sistema girano su quel Python. Cambiarne i pacchetti può romperli — ed è il motivo per cui le versioni recenti di Linux bloccano l'installazione diretta nel Python di sistema.
Il secondo problema è il più pericoloso perché è silenzioso. Il Python di sistema della macchina su cui è stato scritto questo capitolo contiene ancora httpx, pydantic e rich rimasti da vecchi lavori. Quindi qualunque script lì "funziona" — ed è esattamente per questo che non si può capire da lì di cosa ha davvero bisogno uno script.
La convinzione sbagliata è: "Funziona sulla mia macchina, quindi va bene". Uno script che gira sul Python di sistema dimostra solo che, a un certo punto, il pacchetto è stato installato sulla tua macchina. Ciò di cui il progetto ha davvero bisogno si dimostra solo quando tutto viene installato in un ambiente vuoto a partire dal file del progetto, e poi lo script gira.
Un primo progetto con uv
Stando in una cartella di lavoro:
uv init hello-ai --python 3.12
Initialized project `hello-ai` at `D:\ai-lab\hello-ai`(Il percorso alla fine sarà la tua cartella; le trascrizioni di questo capitolo accorciano i percorsi.) uv init crea una nuova cartella, e dentro:
hello-ai/
├── .git/
├── .gitignore
├── .python-version
├── README.md
├── main.py
└── pyproject.tomlIl più importante è pyproject.toml — la carta d'identità del progetto:
[project]
name = "hello-ai"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []dependencies = [] — il progetto non ha ancora bisogno di pacchetti esterni. .python-version contiene solo 3.12: su quale Python gira questo progetto. E uv init ha creato per te un repository Git e un .gitignore — entreranno in gioco nel prossimo capitolo.
Ora eseguilo:
cd hello-ai
uv run main.py
Using CPython 3.12.11
Creating virtual environment at: .venv
Hello from hello-ai!La prima volta, uv run ha creato da solo una cartella .venv — ed è l'ambiente isolato del progetto — e poi ha eseguito main.py con il Python di quell'ambiente. Non hai dovuto attivare nulla.
uv add: aggiungere un pacchetto, e scriverlo
Quasi ogni progetto su cui lavora un AI engineer chiama qualche API, quindi il primo pacchetto è il client HTTP httpx, più python-dotenv per leggere i file .env:
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.0Hai chiesto due pacchetti e ne hai ottenuti otto — gli altri sono le dipendenze di httpx, che uv ha calcolato da solo. I numeri di versione potrebbero essere più recenti quando lo fai tu.
Ora guarda 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",
]Un solo comando ha fatto tre cose: i pacchetti sono stati installati in .venv, pyproject.toml ora registra che il progetto ne ha bisogno, e nel progetto è comparso un nuovo file chiamato uv.lock, che fissa la versione esatta di tutti e otto i pacchetti. Dei lockfile si parlerà più avanti nel corso; per ora basta sapere che un collega che clona il repository ed esegue uv sync ottiene proprio queste otto versioni.
Per rimuovere qualcosa, uv remove:
uv remove python-dotenv
Resolved 8 packages in 21ms
Uninstalled 1 package in 11ms
- python-dotenv==1.2.3Anche questo funziona in entrambi i posti: rimuove il pacchetto da .venv e lo cancella da pyproject.toml.
uv venv, e attivare a mano
uv run crea e usa l'ambiente al posto tuo, quindi in questo corso di solito basta. A volte però ti serve solo un ambiente vuoto — per esempio in un vecchio progetto che non ha ancora un pyproject.toml. Allora:
uv venv --python 3.12
Using CPython 3.12.11
Creating virtual environment at: .venv
Activate with: .venv\Scripts\activateL'ultima riga è quella di Windows PowerShell. Qui cambia da un sistema operativo all'altro:
# Windows (PowerShell)
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activateUna volta attivo, il prompt inizia con (hello-ai) o (.venv), e un semplice comando python esegue il Python di quell'ambiente. Per uscire, deactivate. Ricorda che con uv run nulla di tutto questo serve — è il suo vantaggio, e scrivere uv run nel README di un team è la scelta sicura, perché non esiste lo stato "ho dimenticato di attivare".
Indicare all'editor il Python del progetto
Il programma gira nel terminale, eppure l'editor mostra una sottolineatura rossa sotto import httpx — di solito significa che l'editor sta guardando un altro Python.
VS Code: installa l'estensione Python di Microsoft. Poi apri la cartella del progetto, premi Ctrl + Shift + P (Cmd + Shift + P su macOS) → Python: Select Interpreter → scegli il Python dentro .venv. Se non è in elenco, usa Enter interpreter path e indicagli il percorso: .venv\Scripts\python.exe su Windows, .venv/bin/python su macOS/Linux.
PyCharm: Settings → Project → Python Interpreter → Add Interpreter → Add Local Interpreter → scegli un ambiente esistente e indica lo stesso percorso. Le versioni recenti offrono anche direttamente un ambiente di tipo uv.
Il modo più semplice per essere sicuri di quale Python usi l'editor è eseguire questo nel terminale integrato dell'editor:
import sys
print(sys.executable)Il percorso dovrebbe finire dentro il .venv del tuo progetto — per esempio ...\hello-ai\.venv\Scripts\python.exe. L'inizio del percorso dipende dalla tua cartella, quindi qui non viene mostrato l'output completo.
Un esempio completo
Nel progetto hello-ai, crea un file chiamato env_check.py. È un piccolo script di "controllo dell'ambiente" — quando qualcuno entra in un team, eseguire una cosa del genere per prima conferma che tutto sia al suo posto:
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()Eseguilo dall'interno del progetto:
uv run env_check.pyPython : 3.12
In a venv : True
Env folder : .venv
httpx : 0.28.1
Client ready: True
Hello, AI engineer.Ora eseguiamo lo stesso file in un ambiente vuoto. Il file è stato copiato in un'altra cartella, lì è stato creato un ambiente con uv venv --python 3.12, e il file è stato eseguito direttamente con il Python di quell'ambiente (.venv\Scripts\python env_check.py su Windows, .venv/bin/python env_check.py su 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'(Sulla tua macchina il traceback mostra il percorso completo del file; qui ne è stato mantenuto solo il nome.)
Alcune scelte in questo script meritano attenzione.
sys.prefix != sys.base_prefix — Python stesso sa se sta girando in un ambiente virtuale. sys.base_prefix è il Python di base da cui l'ambiente è stato creato, e sys.prefix è quello che gira adesso. Se sono diversi, sei dentro un ambiente.
Il nome della cartella, non il percorso completo — Path(sys.prefix).name stampa solo l'ultima parte, .venv. Il percorso completo è diverso su ogni macchina; il nome è lo stesso per tutti. Più l'output di uno script di controllo è legato alla macchina, più è difficile confrontarlo nella chat del team.
import httpx a metà della funzione — normalmente gli import vanno in cima al file, e lì devono stare. Qui è messo di proposito a metà, così che in un ambiente vuoto le prime tre righe vengano stampate prima dell'errore. L'output dell'errore racconta la sua storia: Python 3.12 va bene, un ambiente è attivo, ma quell'ambiente non ha httpx. La correzione è uv add httpx — oppure, se il pyproject.toml del progetto lo elenca già, uv sync.
version('httpx') — importlib.metadata è il modo standard per leggere la versione di un pacchetto. Non tutti i pacchetti hanno un __version__, ma ogni pacchetto installato ha dei metadati.
Quando si rompe
The term 'uv' is not recognized as the name of a cmdlet, function, script file, or operable program (su macOS/Linux, uv: command not found) uv è installato, ma il terminale in cui stai scrivendo è stato aperto prima dell'installazione, quindi non conosce il nuovo PATH. Chiudi e riapri il terminale (e, in VS Code, tutto l'editor).
error: No pyproject.toml found in current directory or any parent directory Hai eseguito uv add fuori da una cartella di progetto. uv add scrive nel file del progetto, quindi senza progetto non c'è dove scrivere. Entra nel progetto con cd, oppure esegui prima uv init se è nuovo.
ModuleNotFoundError: No module named 'httpx' Il Python che esegue lo script non ha il pacchetto. Due cause tipiche: il pacchetto non è mai stato aggiunto con uv add, oppure lo script è stato eseguito con python semplice invece che con uv run, quindi ha girato il Python di sistema invece dell'ambiente del progetto. Eseguilo con uv run env_check.py.
error: Failed to spawn: hello.py seguito da Caused by: program not found Hai dato a uv run un nome di file che non c'è nella cartella corrente — di solito un errore di battitura, oppure sei nella cartella sbagliata. Non avendo trovato il file, uv ha cercato un programma con quel nome, ed è per questo che il messaggio sembra strano.
× No solution found when resolving dependencies seguito da Because htpx was not found in the package registry ... Un errore di battitura nel nome del pacchetto (htpx). La buona notizia è che un uv add fallito non cambia nulla — pyproject.toml e uv.lock restano come erano. Correggi il nome e rilancia il comando.
.venv\Scripts\activate : File ... cannot be loaded because running scripts is disabled on this system È una regola di sicurezza di PowerShell. Esegui una volta Set-ExecutionPolicy -Scope CurrentUser RemoteSigned e apri un nuovo terminale — oppure salta l'attivazione ed esegui tutto con uv run.
Passo 4 di 6 — Prevedi
Verifica cosa hai capito
Questo file viene salvato come check.py nel progetto hello-ai ed eseguito con uv run check.py. Cosa viene stampato?
import sys
print(sys.prefix != sys.base_prefix)
print(sys.version_info.major)- A`.venv`, poi `3.12`
- B`True`, poi `3`
- C`True`, poi `12`
- D`False`, poi `3`
Il pyproject.toml del progetto elenca httpx, e uv.lock è nel repository. Eppure un nuovo collega che segue il README su un portatile appena acquistato ottiene ModuleNotFoundError: No module named 'httpx'. Dove sta il bug nel 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__)- AManca un passo che esegue `uv init` dopo il clone
- BIl collega deve prima eseguire `uv add httpx`, poi `python main.py`
- CLa riga `import httpx` deve passare dall'inizio del file a una funzione `main()`
- DIl passo 3 esegue il Python di sistema; dovrebbe dire `uv run main.py`, che crea `.venv` da `pyproject.toml` e `uv.lock` e lo esegue al suo interno
Dopo uv init e uv add, il progetto ha pyproject.toml, uv.lock, .python-version e .venv. Quali di questi finiscono nel repository Git del team?
- ATutto tranne `.python-version`, perché la versione di Python è una scelta personale
- B`pyproject.toml`, `uv.lock` e `.python-version` entrano; `.venv` no
- CTutti e quattro, incluso `.venv`, così i colleghi non devono installare nulla
- DSolo `pyproject.toml`; `uv.lock` è generato, quindi va escluso anche lui
Giocare fa parte di Pro
+30 XP ti aspettano
Gioca questo capitolo con Pro
Leggere è gratis e l’intero capitolo è aperto. I primi 5 capitoli di ogni corso gratuito si giocano gratis. Dal capitolo 6, rispondere alle domande, guadagnare XP e far crescere la serie fa parte di Pro.
Sblocca il gioco con ProTocca a te
Con uv e Python 3.12 pronti sulla tua macchina, crea un nuovo progetto:
- Crea il progetto con
uv init my-first-agent --python 3.12, e aggiungi un pacchetto conuv add httpx - Scrivi nel progetto il file
env_check.pyqui sopra esattamente com'è, ed eseguilo conuv run env_check.py - Apri
pyproject.tomle mostra chehttpxè elencato sottodependencies, e che nel progetto è stato creato un fileuv.lock - Apri il progetto in VS Code o PyCharm e seleziona il
.venvdel progetto come interprete, così non c'è nessuna sottolineatura rossa sulla rigaimport httpx
Output atteso (la versione di httpx potrebbe essere più recente quando lo fai tu):
Python : 3.12
In a venv : True
Env folder : .venv
httpx : 0.28.1
Client ready: True
Hello, AI engineer.Poi rompilo di proposito: esegui uv remove httpx e poi di nuovo uv run env_check.py. Annota fino a dove stampa, quale errore compare, e cosa è cambiato in pyproject.toml. Poi sistemalo con uv add httpx. Questo ciclo di rottura e riparazione richiede due minuti, ma nella prima settimana del tuo primo lavoro è la cosa che ti farà risparmiare più tempo.
Passo 6 di 6
Sfida — il quiz del capitolo
Dieci domande dalla più facile alla più difficile. Le ultime sono difficili di proposito.
Gioca con Pro