Torna al blog

Risoluzione dei problemiGuida

UnicodeEncodeError quando stampi una risposta LLM in Python: 3 soluzioni

print(reply) va in crash con cirillico o emoji? Scopri perché Python fallisce con output rediretto o una code page legacy, e risolvilo con la modalità UTF-8, reconfigure o encoding=.

Di CheapTokens TeamPubblicato il 6 min di lettura

UnicodeEncodeError su print(reply) e la soluzione UTF-8, disegnati come una scheda di errore
In questa pagina
  1. Come si presenta l'errore
  2. Controlla quale codifica hai davvero
  3. Soluzione 1: attiva la modalità UTF-8
  4. Soluzione 2: riconfigura stdout dentro lo script
  5. Soluzione 3: dai ai file una codifica esplicita
  6. Quale soluzione dovresti usare?
  7. Se fallisce ancora

La tua richiesta è andata a buon fine, il modello ha risposto, e poi Python è morto su print(reply). L'API non c'entra. La risposta è corretta; il posto in cui la stampi non riesce a rappresentare alcuni dei suoi caratteri. La soluzione più rapida è attivare la modalità UTF-8 con PYTHONUTF8=1. Se preferisci tenerlo dentro lo script, chiama sys.stdout.reconfigure(encoding="utf-8") in cima, e quando salvi una risposta su file, passa encoding="utf-8" a open().

Come si presenta l'errore#

Supponi di fare una domanda a un modello in russo e di stampare la risposta. Questo è lo script completo, che usa la semplice chiamata requests della nostra guida alla prima richiesta:

python
import os, requests

r = requests.post(
    "https://api.cheaptokens.dev/v1/chat/completions",
    headers={"Authorization": f"Bearer {os.environ['CHEAPTOKENS_API_KEY']}"},
    json={
        "model": "deepseek-ai/DeepSeek-V4-Flash-0731",
        "messages": [{"role": "user", "content": "Ответь одним предложением: что такое токен?"}],
        "max_tokens": 200,
    },
)
reply = r.json()["choices"][0]["message"]["content"]
print(reply)

Quando stdout è rediretto su un file o una pipe, oppure Python è stato avviato con una code page legacy per i suoi stream, l'ultima riga termina così:

text
UnicodeEncodeError: 'charmap' codec can't encode characters in position 0-5: character maps to <undefined>

Il nome del codec nel tuo messaggio dipende dalla codifica dello stream (per una code page di Windows di solito è charmap, per ascii è ascii), e le posizioni dipendono dalla risposta. La forma è sempre la stessa: il traceback punta a print, non alla richiesta.

Un traceback UnicodeEncodeError che punta a print(reply)
Forma tipica dell'errore: viene sollevato da print, dopo che la chiamata API è già riuscita

Perché succede? print converte il testo in byte usando la codifica di sys.stdout. Se quella codifica è una code page legacy, qualsiasi carattere al di fuori di essa, come il cirillico in una code page occidentale, un'emoji, a volte un trattino tipografico, non ha un byte in cui trasformarsi. Python solleva un'eccezione invece di indovinare.

Si manifesta in tre situazioni:

  • stdout è rediretto o in pipe (python app.py > out.txt, | another program), oppure lo script viene eseguito da uno scheduler, da una CI o da un editor in cui stdout non è una console;
  • PYTHONLEGACYWINDOWSSTDIO è impostata, oppure lo stream riceve comunque una codifica ristretta;
  • scrivi la risposta su un file con open(path, "w") e senza encoding=.

Quale Python? Tutto quanto segue riguarda Python 3.7–3.14, dove la codifica degli stream e dei file deriva dal sistema. Secondo il PEP 686 (stato Final, https://peps.python.org/pep-0686/, verificato il 5 novembre 2026), la modalità UTF-8 è attiva per impostazione predefinita da Python 3.15, quindi open() e stdio usano già UTF-8 lì, a meno che qualcuno non l'abbia disattivata con PYTHONUTF8=0 o -X utf8=0. Verifica con python --version.

Controlla quale codifica hai davvero#

Prima di cambiare qualcosa, guarda cosa ha scelto Python. Bastano dieci secondi.

Provalo tu stessoProvalo: secondo Python, qual è la codifica del tuo stdout?Mostra risposta

Esegui python -c "import sys; print(sys.stdout.encoding)" nella stessa finestra in cui lo script fallisce. In una console interattiva di solito stampa utf-8, quindi da solo dimostra poco. Eseguilo di nuovo con > check.txt in fondo e apri il file: l'output rediretto è ciò che più spesso dà un nome cp… o ascii, ed è il tuo colpevole. Se tutto dice utf-8, guarda un file su cui scrivi.

Vuoi vedere il crash senza aspettare una giornata storta? Su macOS o Linux, forza una codifica ristretta per una singola esecuzione:

bash
PYTHONIOENCODING=ascii python -c "print('Привет')"

Fallisce con un messaggio del codec ascii, della stessa famiglia dell'errore qui sopra. Su Windows la variabile viene ignorata per una console interattiva, ma funziona quando l'output è rediretto: in cmd esegui set PYTHONIOENCODING=ascii, poi python -c "print('Привет')" > out.txt (in PowerShell: $env:PYTHONIOENCODING = "ascii").

Soluzione 1: attiva la modalità UTF-8#

Python ha una modalità che rende UTF-8 la codifica predefinita per il testo. Secondo la documentazione di Python (pagina della riga di comando, verificata il 5 novembre 2026), PYTHONUTF8=1 la attiva e -X utf8 fa lo stesso; entrambe esistono da Python 3.7. Un'avvertenza dalla stessa pagina: qualsiasi altro valore non vuoto di PYTHONUTF8 causa un errore all'avvio, quindi usa esattamente 1 (o 0 per disattivarla). Su 3.15 ti serve solo per attivare esplicitamente la modalità su interpreti più vecchi; se lì è già attiva, cerca PYTHONUTF8=0 nel tuo ambiente.

Attiva la modalità UTF-8 per una singola esecuzione

cmd

bat
set PYTHONUTF8=1
python app.py

PowerShell

powershell
$env:PYTHONUTF8 = "1"
python app.py

macOS / Linux

bash
PYTHONUTF8=1 python app.py

Nessuna modifica al codice, e copre la console, i redirect e i file in quell'esecuzione. Se non vuoi impostare una variabile ogni volta, python -X utf8 app.py dà lo stesso risultato dalla riga di comando.

C'è anche PYTHONIOENCODING=utf-8, che sovrascrive solo la codifica di stdin, stdout e stderr. Leggi la sua voce nella documentazione prima di affidarti a essa su Windows: da Python 3.6 viene ignorata per un buffer di console interattiva a meno che PYTHONLEGACYWINDOWSSTDIO non sia impostata. File e pipe rediretti non sono interessati da quell'eccezione. Quindi può risolvere python app.py > out.txt e comunque non fare nulla nella finestra della console. Per stderr l'error handler è sempre backslashreplace.

Soluzione 2: riconfigura stdout dentro lo script#

Se non puoi controllare come le persone avviano lo script, cambia lo stream stesso in cima al file:

python
import sys

sys.stdout.reconfigure(encoding="utf-8")
sys.stderr.reconfigure(encoding="utf-8")

print(reply)

reconfigure è documentato per io.TextIOWrapper (aggiunto in 3.7). Quando passi encoding e ometti errors, l'handler è strict, quindi un carattere che non rientra solleva comunque un'eccezione; nel caso comune di UTF-8 non resta nulla fuori. Due dettagli dalla documentazione: la codifica non può essere cambiata una volta che sono stati letti dati dallo stream (può esserlo dopo una scrittura), e encoding="locale" è supportato da 3.11.

Ti serve che lo script non vada mai in crash, nemmeno su un terminale che davvero non riesce a mostrare il testo? Aggiungi errors="replace". I caratteri sconosciuti appaiono allora come ? invece di fermare l'esecuzione. Questo nasconde il problema invece di risolverlo, quindi tienilo per i log.

Soluzione 3: dai ai file una codifica esplicita#

Salvare una risposta è lo stesso errore, solo più silenzioso nel codice:

python
# before: on Python up to 3.14 this uses the system's default encoding
with open("reply.txt", "w") as f:
    f.write(reply)

# after: the file is UTF-8 on every machine
with open("reply.txt", "w", encoding="utf-8") as f:
    f.write(reply)

Usa lo stesso encoding="utf-8" quando rileggi il file, altrimenti il testo può rompersi in ingresso.

Prima: print(reply) solleva UnicodeEncodeError. Dopo: la stessa riga stampa la risposta completa
La stessa riga print, prima e dopo la modalità UTF-8

Quale soluzione dovresti usare?#

Scegli il tuo caso

Scegli il tuo caso

Eseguo il mio script in un terminale

Imposta PYTHONUTF8=1 una volta nel tuo ambiente, oppure avvia con python -X utf8 app.py. Nulla nel codice cambia.

Distribuisco lo script ad altre persone

Metti sys.stdout.reconfigure(encoding="utf-8") in cima, così funziona comunque lo avviino.

Il crash è su un file, non sullo schermo

Aggiungi encoding="utf-8" a open(), sia in scrittura che in lettura.

Puoi combinarle. Uno script che stampa e salva risposte ha bisogno della Soluzione 2 o della Soluzione 1 per lo schermo e della Soluzione 3 per il file.

Se fallisce ancora#

  • L'errore si è spostato su un'altra riga. Allora la chiamata che fallisce è un'altra print o write; la soluzione deve essere applicata prima che venga eseguita, quindi metti reconfigure in cima al file.
  • L'errore menziona PYTHONUTF8. La variabile ha un valore diverso da 1 o 0. Rimuovila e impostala di nuovo.
  • Nessun crash, ma vedi quadrati o ? nella console. Python ha scritto UTF-8 valido; il font o la code page della console non riescono a mostrarlo. Redirigi su un file e aprilo in un editor per confermare che la risposta sia intatta.
  • L'errore è un JSONDecodeError, non un UnicodeEncodeError. Problema diverso: vedi come estrarre JSON da una risposta del modello.

Il codice della richiesta qui sopra è la semplice chiamata requests; la documentazione di CheapTokens mostra la stessa chiamata per l'SDK OpenAI. Un altro modello funziona con la stessa soluzione: sostituisci il campo model con zai-org/GLM-5.3-Flash (fino a 8.192 token di output per risposta, 390K di contesto). L'errore di codifica non ha nulla a che fare con il modello, solo con dove va il testo.