Vai al contenuto
di tendenza

Guide

Prima chiamata alle API AI in Python: guida passo passo

Come iniziare con le API AI in Python: venv su Windows, libreria openai con OpenRouter, streaming e gestione errori 401/429/500 con retry.

Testo: 12 min di lettura

👁 114 letture

La prima chiamata a un modello di intelligenza artificiale in Python richiede solo dieci righe di codice: installi la libreria openai, indichi l’endpoint e la chiave API, invii un elenco di messaggi e leggi la risposta. Qui analizziamo l’intero flusso dall’installazione di Python su Windows, passando per l’ambiente virtuale (venv), fino allo streaming, alla gestione degli errori e ai tentativi automatici (retry). Ogni script è stato eseguito il 4 ottobre 2026 su Windows 11 con Python 3.13.15 tramite OpenRouter, mostrando l’output reale ottenuto. È il terzo passaggio del percorso API AI da zero.

Configurazione di test (4 ottobre 2026)

  • Windows 11 Pro, Python 3.13.15, librerie: openai 3.24.0, python-dotenv 1.2.4, pydantic 2.13.5.
  • Node.js 26.10 con libreria openai 7.27.0 (versione JavaScript a fine articolo).
  • Accesso ai modelli: OpenRouter, modello predefinito openai/gpt-6-luna (circa 0,089 EUR / 0,447 EUR, ossia 0,10 / 0,50 USD per milione di token, tasso BCE del 12/10/2026: 1 EUR = 1,1181 USD da ecb.europa.eu).
  • Costo totale di tutte le esecuzioni dell’articolo: circa 0,0045 EUR (0,005 USD).

Installare Python su Windows

  1. Visita python.org/downloads e scarica il programma di installazione per Windows (Python 3.13 o successivo; la libreria openai richiede almeno la versione 3.10).
  2. Nella prima schermata dell’installer seleziona la casella Add python.exe to PATH. Senza questa opzione il terminale non troverà l’eseguibile, ed è l’ostacolo più comune per chi comincia.
  3. In alternativa, da terminale puoi eseguire: winget install Python.Python.3.13.
  4. Apri una nuova finestra di PowerShell o Terminale Windows e digita: python --version. Dovresti visualizzare la versione installata anziché l’apertura del Microsoft Store.

Se viene avviato il Microsoft Store, vai in Impostazioni → App → Impostazioni avanzate per le app → Alias di esecuzione delle app e disattiva gli alias per python.exe e python3.exe.

Creare l’ambiente virtuale (venv)

Un ambiente virtuale (venv) è uno spazio isolato dedicato alle dipendenze di uno specifico progetto, evitando conflitti tra librerie. Si crea una sola volta nella cartella di lavoro:

mkdir mie-api
cd mie-api
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install openai python-dotenv

Una volta attivato, vedrai il prefisso (.venv) all’inizio della riga del terminale. Se PowerShell blocca l’esecuzione dello script, esegui una volta il comando Set-ExecutionPolicy -Scope CurrentUser RemoteSigned. In ambienti Git Bash usa source .venv/Scripts/activate, mentre su Linux e macOS il comando è source .venv/bin/activate.

La chiave API va salvata in un file chiamato .env all’interno della cartella principale (con una riga simile a: OPENROUTER_API_KEY=sk-or-v1-...). Per i dettagli su come generarla e proteggerla, consulta la guida su come gestire le chiavi API in sicurezza.

La prima chiamata API

In questo esempio utilizziamo l’SDK ufficiale di OpenAI configurato con l’endpoint di OpenRouter. Poiché il formato delle richieste è identico, con una singola chiave puoi interrogare modelli di OpenAI, Anthropic, Google, DeepSeek e molti altri, modificando solo il nome del modello.

"""Prima chiamata a un modello AI tramite OpenRouter (SDK openai)."""
import os
from dotenv import load_dotenv
from openai import OpenAI

load_dotenv()  # carica le variabili dal file .env nella directory corrente

client = OpenAI(
    base_url="https://openrouter.ai/api/v1",
    api_key=os.environ["OPENROUTER_API_KEY"],
)

# Il test originale è stato inviato con prompt in polacco
odpowiedz = client.chat.completions.create(
    model=os.getenv("MODEL", "openai/gpt-6-luna"),
    messages=[
        {"role": "system", "content": "[Traduzione del prompt originale in polacco: Rispondi in polacco, brevemente e nello specifico.]"},
        {"role": "user", "content": "[Traduzione del prompt originale in polacco: Spiega in due frasi che cos'è un'API.]"},
    ],
)

print(odpowiedz.choices[0].message.content)
print("---")
print("modello:", odpowiedz.model)
print("token input:", odpowiedz.usage.prompt_tokens)
print("token output:", odpowiedz.usage.completion_tokens)
szczegoly = odpowiedz.usage.completion_tokens_details
if szczegoly and szczegoly.reasoning_tokens:
    print("  di cui token di ragionamento:", szczegoly.reasoning_tokens)
koszt = getattr(odpowiedz.usage, "cost", None)  # OpenRouter include il costo in USD
if koszt is not None:
    print(f"costo: {koszt:.6f} USD")

Analisi del flusso di esecuzione:

  • load_dotenv() carica la chiave definita nel file .env all’interno delle variabili d’ambiente di sistema;
  • OpenAI(base_url=..., api_key=...) inizializza il client. Senza specificare base_url, le chiamate punterebbero direttamente ai server OpenAI;
  • messages contiene la cronologia dei messaggi: il ruolo system imposta le istruzioni operative, mentre user contiene la richiesta vera e propria (ulteriori dettagli su ruoli e iperparametri sono descritti nell’approfondimento su system prompt, temperatura e finestra di contesto);
  • odpowiedz.choices[0].message.content contiene la risposta generata dal modello;
  • usage restituisce il consumo dei token, con l’estensione cost fornita da OpenRouter per indicare la spesa in dollari.

Questo l’output registrato sul sistema di test con il modello predefinito GPT-6 Luna (risposta generata in polacco, lingua utilizzata per la prova):

[Traduzione dal test originale in polacco: Un'API è un insieme di regole e strumenti grazie ai quali programmi diversi possono comunicare tra loro. Definisce come inviare richieste e ricevere dati o funzionalità da un altro sistema.]
---
modello: openai/gpt-6-luna
token input: 40
token output: 58
costo: 0.000033 USD

In base al cambio di riferimento BCE del 12/10/2026 (1 EUR = 1,1181 USD), 0,000033 USD equivalgono a circa 0,000030 EUR. Eseguendo la medesima richiesta con Gemini 3.8 Flash (modificando unicamente la variabile MODEL):

[Traduzione dal test originale in polacco: Un'API (Interfaccia di Programmazione delle Applicazioni) è un insieme di regole che consente a programmi e sistemi differenti di comunicare in sicurezza e scambiare dati tra loro. Funziona da intermediario, permettendo a un'applicazione di utilizzare le funzioni o le risorse di un'altra senza la necessità di conoscerne la struttura interna.]
---
modello: google/gemini-3.8-flash
token input: 29
token output: 462
  di cui token di ragionamento: 390
costo: 0.001754 USD

0,001754 USD corrispondono a circa 0,001569 EUR (tasso BCE del 12/10/2026). Si noti il conteggio: Gemini ha restituito 462 token di output per una risposta breve poiché 390 sono stati impiegati nella fase di elaborazione interna (“ragionamento”). Poiché anche questi token vengono fatturati, il costo complessivo è risultato nettamente superiore rispetto a Luna. Per monitorare la spesa è fondamentale verificare sempre il blocco usage anziché la sola lunghezza del testo finale, come illustrato nell’articolo su cosa sono i token e quanto costano.

Streaming: ricevere la risposta in tempo reale

In modalità standard la risposta viene restituita solo al termine completo della generazione. Con lo streaming i token vengono inviati progressivamente via via che vengono prodotti, riducendo la latenza percepita nelle interfacce interattive.

"""Streaming: la risposta viene emessa progressivamente come nelle chat web."""
import os
from dotenv import load_dotenv
from openai import OpenAI

load_dotenv()
client = OpenAI(base_url="https://openrouter.ai/api/v1", api_key=os.environ["OPENROUTER_API_KEY"])

# Test originale eseguito con prompt in polacco (richiesta di 5 nomi per un blog di cucina)
strumien = client.chat.completions.create(
    model=os.getenv("MODEL", "openai/gpt-6-luna"),
    messages=[{"role": "user", "content": "[Traduzione del prompt originale in polacco: Fornisci 5 idee per il nome di un blog di cucina. Solo l'elenco.]"}],
    stream=True,
    stream_options={"include_usage": True},  # include il conteggio finale dei token
)

for kawalek in strumien:
    if kawalek.choices and kawalek.choices[0].delta.content:
        print(kawalek.choices[0].delta.content, end="", flush=True)
    if kawalek.usage:  # presente solo nell'ultimo blocco ricevuto
        print(f"\n--- token: {kawalek.usage.prompt_tokens} input, {kawalek.usage.completion_tokens} output")

Output ottenuto durante il test:

[Traduzione dal test originale in polacco:]
1. Direttamente dalla padella
2. Un pizzico di sapore
3. Cucina con la testa
4. Con la forchetta sul piatto
5. Rifugio culinario
--- token: 20 input, 439 output

Nelle sessioni in streaming il resoconto dei token non è presente nei singoli frammenti di testo: per ottenerlo è necessario specificare il parametro stream_options={"include_usage": True}, che lo allega all’ultimo blocco.

Gestione degli errori e tentativi automatici (retry)

Nei sistemi in produzione le chiamate API possono fallire per svariati motivi: parametri errati, rate limiting (codice HTTP 429) o disservizi temporanei dell’infrastruttura (5xx). La gestione segue due principi:

  • Gli errori lato client (400, 401, 403, 404) non vanno ritentati: una richiesta identica fallirebbe nuovamente, rendendo necessaria una correzione nel codice o nelle credenziali;
  • Gli errori transitori (429, 500, 502, 503, problemi di rete) vanno ritentati con ritardo progressivo (exponential backoff: 2s, 4s, 8s) arricchito da un valore casuale (jitter) per evitare picchi simultanei sul server.
"""Gestione errori API: 401, 429, 5xx e logica di retry con backoff esponenziale."""
import os, sys, time, random
from dotenv import load_dotenv
import openai
from openai import OpenAI

load_dotenv()
client = OpenAI(
    base_url=os.getenv("BASE_URL", "https://openrouter.ai/api/v1"),
    api_key=os.environ.get("OPENROUTER_API_KEY", ""),
    max_retries=0,   # disattiviamo il retry integrato per implementare la logica esplicita
    timeout=60,      # timeout in secondi per evitare blocchi indefiniti
)


def zapytaj(domanda, model, tentativi=4):
    for tentativo in range(1, tentativi + 1):
        try:
            r = client.chat.completions.create(model=model, messages=[{"role": "user", "content": domanda}])
            return r.choices[0].message.content
        except openai.AuthenticationError as e:      # 401 - chiave errata o disattivata
            sys.exit(f"401: verifica la chiave API ({e.message})")
        except openai.PermissionDeniedError as e:    # 403 - permessi insufficienti o restrizioni geografiche
            sys.exit(f"403: accesso negato ({e.message})")
        except openai.NotFoundError as e:            # 404 - modello o endpoint inesistente
            sys.exit(f"404: modello o endpoint non trovato ({e.message})")
        except openai.BadRequestError as e:          # 400 - parametri della richiesta errati
            sys.exit(f"400: richiesta non valida ({e.message})")
        except (openai.RateLimitError, openai.InternalServerError,
                openai.APIConnectionError, openai.APITimeoutError) as e:
            # 429 (rate limit), 5xx (errore server), caduta di connessione
            if tentativo == tentativi:
                raise
            pausa = 2 ** tentativo + random.random()   # 2, 4, 8 s + jitter casuale
            codice = getattr(e, "status_code", "rete")
            print(f"[tentativo {tentativo}] errore {codice}, attesa di {pausa:.1f} s...")
            time.sleep(pausa)
        except openai.APIStatusError as e:           # altri codici di errore
            sys.exit(f"{e.status_code}: {e.message}")


if __name__ == "__main__":
    model = sys.argv[1] if len(sys.argv) > 1 else os.getenv("MODEL", "openai/gpt-6-luna")
    print(zapytaj("Quanto fa 17 * 23? Rispondi solo con il numero.", model))

Durante il test sono stati verificati diversi scenari. Risposta a una richiesta corretta:

391

In caso di chiave non valida oppure identificativo del modello inesistente (OpenRouter risponde con codice 400 se l’ID non è riconosciuto):

401: verifica la chiave API (Error code: 401 - {'error': {'message': 'User not found.', 'code': 401}})
400: richiesta non valida (Error code: 400 - {'error': {'message': 'openai/gpt-7-nie-istnieje is not a valid model ID', 'code': 400}})

Per simulare in modo affidabile l’errore 429 senza saturare gli account reali, è stato impiegato un server di simulazione locale che respinge le prime due chiamate con codice 429 e risponde regolarmente alla terza:

"""Mock server per simulare risposte 429 e verificare la logica di retry."""
import json
from http.server import BaseHTTPRequestHandler, HTTPServer

conteggio = {"n": 0}


class Handler(BaseHTTPRequestHandler):
    def do_POST(self):
        self.rfile.read(int(self.headers.get("Content-Length", 0)))
        conteggio["n"] += 1
        if conteggio["n"] <= 2:
            codice, payload = 429, {"error": {"message": "Rate limit exceeded (test)", "code": 429}}
        else:
            codice, payload = 200, {
                "id": "test-1", "object": "chat.completion", "created": 0, "model": "test-model",
                "choices": [{"index": 0, "finish_reason": "stop",
                             "message": {"role": "assistant", "content": "391"}}],
                "usage": {"prompt_tokens": 10, "completion_tokens": 1, "total_tokens": 11},
            }
        corpo = json.dumps(payload).encode()
        self.send_response(codice)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(corpo)))
        self.end_headers()
        self.wfile.write(corpo)
        print(f"chiamata {conteggio['n']} -> {codice}")


HTTPServer(("127.0.0.1", 8429), Handler).serve_forever()

Il log di esecuzione mostra l’efficacia del backoff esponenziale:

[tentativo 1] errore 429, attesa di 2.8 s...
[tentativo 2] errore 429, attesa di 4.2 s...
391

La libreria openai include già un sistema di retry nativo (configurabile tramite max_retries, di default impostato su 2 tentativi). Negli applicativi reali è spesso sufficiente affidarsi a tale opzione impostando un valore prudenziale come max_retries=5.

Buone pratiche operative:

  • Definire sempre un timeout. Senza indicazioni specifiche il client può attendere fino a 10 minuti. I modelli dotati di ragionamento prolungato possono richiedere più tempo rispetto ai 60 secondi standard;
  • Registrare il costo delle chiamate. Salvare periodicamente i valori di usage.cost consente di monitorare la spesa reale rispetto alle stime teoriche;
  • Distinguere l’esaurimento crediti dal rate limit temporaneo. Su alcune piattaforme l’esaurimento del budget restituisce anch’esso un codice 429, ma un ciclo di retry automatico non risolverà il problema senza ricaricare l’account.

Esempio equivalente in JavaScript (Node.js)

L’SDK openai per l’ambiente Node.js presenta una struttura del tutto speculare. Utilizzando Node.js 26.10, i pacchetti openai (7.27.0) e dotenv (18.0.5) e la configurazione "type": "module" in package.json, il seguente script copre chiamata standard, streaming e cattura dell’errore:

// Chiamata di esempio in Node.js tramite OpenRouter
import "dotenv/config";
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://openrouter.ai/api/v1",
  apiKey: process.env.OPENROUTER_API_KEY,
});
const model = process.env.MODEL ?? "openai/gpt-6-luna";

// 1. Chiamata standard (prompt di test originale formulato in polacco)
const r = await client.chat.completions.create({
  model,
  messages: [
    { role: "system", content: "[Traduzione del prompt originale in polacco: Rispondi in polacco, brevemente.]" },
    { role: "user", content: "[Traduzione del prompt originale in polacco: In che cosa differisce JavaScript da Java? Una sola frase.]" },
  ],
});
console.log(r.choices[0].message.content);
console.log(`--- ${r.usage.prompt_tokens} + ${r.usage.completion_tokens} token, costo ${r.usage.cost} USD\n`);

// 2. Streaming (richiesta originale in polacco di elencare 3 fiumi)
const strumien = await client.chat.completions.create({
  model,
  messages: [{ role: "user", content: "[Traduzione del prompt originale in polacco: Elenca 3 fiumi polacchi. Solo i nomi separati da virgola.]" }],
  stream: true,
});
for await (const kawalek of strumien) {
  process.stdout.write(kawalek.choices[0]?.delta?.content ?? "");
}
console.log();

// 3. Gestione errori: identificativo del modello non valido
try {
  await client.chat.completions.create({ model: "non/esiste", messages: [{ role: "user", content: "test" }] });
} catch (e) {
  if (e instanceof OpenAI.APIError) console.log(`Errore ${e.status}: ${e.message}`);
  else throw e;
}

Output ottenuto dall’esecuzione (risposte generate in polacco come da prompt di test):

[Traduzione dal test originale in polacco: JavaScript è un linguaggio dinamico utilizzato principalmente nei browser e nelle applicazioni web, mentre Java è un linguaggio distinto, tipizzato staticamente e compilato per l'esecuzione sulla JVM.]
--- 39 + 54 token, costo 0.0000309 USD

[Traduzione dal test originale in polacco: Vistola, Oder, Warta]
Errore 400: 400 non/esiste is not a valid model ID

0,0000309 USD equivalgono a circa 0,0000276 EUR (al tasso BCE del 12/10/2026: 1 EUR = 1,1181 USD). Le differenze rispetto a Python sono minime: la proprietà baseURL al posto di base_url, la sintassi await e il costrutto for await per scorrere il flusso asincrono.

File di esempio pronti all’uso

Il codice mostrato in questa sezione fa parte del pacchetto introduttivo disponibile nella risorsa starter kit API con schema .env.example di supporto. Per avviare il test è sufficiente configurare le proprie credenziali ed eseguire lo script principale.

Approfondimenti successivi

  • Regolazione dei parametri: system prompt, temperatura, finestra di contesto e max tokens.
  • Output strutturato in formato JSON: guida completa allo structured output.
  • Calcolo preventivo dei costi: calcolatore di token per API AI.
  • Automazione e workflow complessi: percorso su Agenti AI da zero e implementazione del primo agente in Python.

Domande frequenti

È obbligatorio usare OpenRouter con l’API OpenAI?

No. Se disponi di una chiave API OpenAI diretta, è sufficiente rimuovere il parametro base_url e inserire il modello standard (ad esempio gpt-6-luna). Nel testo dedicato a come gestire le chiavi API trovi gli esempi di connessione diretta con OpenAI, Anthropic e Google.

Cosa fare se compare l’errore ModuleNotFoundError: No module named ‘openai’?

La libreria è stata installata in un ambiente Python diverso da quello in esecuzione. Verifica di aver attivato il venv (.venv\Scripts\Activate.ps1) prima di lanciare lo script oppure avvialo specificando il percorso dell’interprete: .venv\Scripts\python.

Come risolvere KeyError: ‘OPENROUTER_API_KEY’?

Lo script non rileva la variabile d’ambiente. Assicurati che il file si chiami esattamente .env (evitando estensioni nascoste come .env.txt su Windows), sia collocato nella root del progetto e non presenti spaziature prima o dopo il segno di uguale.

Chat Completions API o Responses API?

Per i nuovi progetti OpenAI suggerisce la nuova interfaccia Responses API, ma Chat Completions rimane lo standard universale compatibile con OpenRouter, DeepSeek, Mistral e sistemi locali come Ollama. È la scelta ideale per apprendere i concetti di base con codice riutilizzabile.

Quanto costa sperimentare con le API?

I costi per i test di sviluppo sono estremamente contenuti. I test completi eseguiti per questo articolo hanno comportato una spesa complessiva di circa mezzo centesimo di dollaro (circa 0,0045 EUR). Inoltre diversi fornitori e cataloghi come OpenRouter offrono modelli contrassegnati dal suffisso :free con cui fare pratica a costo zero.

Google · Le tue fontiPiù in alto su Google con un solo clicAggiungi alle fonti preferite →

Fonti e documentazione tecnica

Kinetyra

// read next

More on this from NITIDO

Nitido

Nitido

ADMINISTRATOR
leggi ancheguideCos’è un’API? Spiegazione con l’AI e prima chiamata curlCos'è un'API: richieste e risposte, formato JSON, metodi HTTP, codici di errore 401, 429, 500 e la tua prima chiamata con curl verso un modello di AI.

Più letti

  1. 1Seedance di ByteDance: versioni, prezzi e test
  2. 2Claude Sonnet 5.5 prezzo: quanto costa nel 2026
  3. 325 matematici Fields Medal firmano lettera aperta contro OpenAI
// mappa del sito

Questa pagina in altre lingue6

nitido in numeri 0testi in archivio0notizie degli ultimi 7 giorni0modelli video nell'osservatorio
× ‹ ingrandimento ›