Khắc phục sự cốHướng dẫn
UnicodeEncodeError khi in câu trả lời LLM trong Python: 3 cách sửa
print(reply) crash với chữ Cyrillic hoặc emoji? Xem tại sao Python thất bại với đầu ra bị chuyển hướng hoặc code page cũ, và sửa bằng chế độ UTF-8, reconfigure hoặc encoding=.

Trên trang này
Yêu cầu của bạn đã được gửi đi, mô hình đã trả lời, và rồi Python chết trên print(reply). API không có lỗi. Câu trả lời vẫn ổn; nơi bạn in nó ra không thể biểu diễn một số ký tự của nó. Cách sửa nhanh nhất là bật chế độ UTF-8 bằng PYTHONUTF8=1. Nếu bạn muốn giữ nó trong script, hãy gọi sys. ở đầu, và khi lưu câu trả lời ra file, truyền encoding="utf-8" cho open().
Lỗi trông như thế nào#
Giả sử bạn hỏi mô hình một câu bằng tiếng Nga và in câu trả lời. Đây là toàn bộ script, dùng lệnh gọi requests đơn giản từ hướng dẫn yêu cầu đầu tiên của chúng tôi:
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)Khi stdout được chuyển hướng ra file hoặc pipe, hoặc Python được khởi động với một code page cũ cho các luồng của nó, dòng cuối cùng kết thúc như sau:
UnicodeEncodeError: 'charmap' codec can't encode characters in position 0-5: character maps to <undefined>Tên codec trong thông báo của bạn phụ thuộc vào encoding của luồng (với code page Windows thường là charmap, với ascii là ascii), và các vị trí phụ thuộc vào câu trả lời. Hình dạng luôn giống nhau: traceback trỏ vào print, không phải vào yêu cầu.

Tại sao lại xảy ra? print chuyển văn bản thành byte bằng encoding của sys.stdout. Nếu encoding đó là một code page cũ, bất kỳ ký tự nào nằm ngoài nó, chẳng hạn chữ Cyrillic trong code page phương Tây, emoji, đôi khi là dấu gạch ngang kiểu chữ, đều không có byte để chuyển thành. Python raise thay vì đoán.
Nó xuất hiện trong ba tình huống:
- stdout bị chuyển hướng hoặc pipe (
python app.,py > out. txt | another program), hoặc script chạy từ scheduler, CI hay editor nơi stdout không phải console; PYTHONLEGACYWINDOWSSTDIOđược đặt, hoặc luồng nhận một encoding hẹp;- bạn ghi câu trả lời ra file bằng
open(path, "w")mà không cóencoding=.
Python nào? Mọi thứ bên dưới nói về Python 3.7–3.14, nơi encoding của luồng và file lấy từ hệ thống. Theo PEP 686 (trạng thái Final, https://peps.python.org/pep-0686/, kiểm tra ngày 5 tháng 11 năm 2026), chế độ UTF-8 được bật mặc định từ Python 3.15, nên open() và stdio đã dùng UTF-8 ở đó trừ khi ai đó tắt nó bằng PYTHONUTF8=0 hoặc -X utf8=0. Kiểm tra bằng python --version.
Kiểm tra encoding bạn thực sự có#
Trước khi thay đổi bất cứ điều gì, hãy xem Python đã chọn gì. Mất mười giây.
Tự mình thử xemThử xem: Python nghĩ encoding stdout của bạn là gì?Hiện đáp án
Chạy python - trong cùng cửa sổ nơi script thất bại. Trong console tương tác nó thường in utf-8, nên chỉ riêng điều đó chứng minh được ít. Chạy lại với > check.txt ở cuối và mở file: đầu ra bị chuyển hướng là thứ thường cho ra tên cp… hoặc ascii hơn, và đó là thủ phạm của bạn. Nếu mọi thứ đều nói utf-8, hãy xem file bạn ghi ra.
Muốn thấy crash mà không cần chờ một ngày xấu? Trên macOS hoặc Linux, ép một encoding hẹp cho một lần chạy:
PYTHONIOENCODING=ascii python -c "print('Привет')"Lệnh đó thất bại với thông báo codec ascii, cùng họ với lỗi trên. Trên Windows biến này bị bỏ qua với console tương tác, nhưng nó hoạt động khi đầu ra bị chuyển hướng: trong cmd chạy set PYTHONIOENCODING=ascii, rồi python - (trong PowerShell: $env:PYTHONIOENCODING = "ascii").
Cách sửa 1: bật chế độ UTF-8#
Python có một chế độ biến UTF-8 thành mặc định cho văn bản. Theo tài liệu Python (trang command-line, kiểm tra ngày 5 tháng 11 năm 2026), PYTHONUTF8=1 bật nó và -X utf8 làm điều tương tự; cả hai đều có từ Python 3.7. Một lưu ý từ cùng trang: bất kỳ giá trị khác không rỗng nào của PYTHONUTF8 đều gây lỗi khi khởi động, nên hãy dùng đúng 1 (hoặc 0 để tắt nó). Trên 3.15 bạn chỉ cần điều này để bật chế độ một cách tường minh trên các interpreter cũ hơn; nếu nó đã bật ở đó, hãy tìm PYTHONUTF8=0 trong môi trường của bạn.
Bật chế độ UTF-8 cho một lần chạy
cmd
set PYTHONUTF8=1
python app.pyPowerShell
$env:PYTHONUTF8 = "1"
python app.pymacOS / Linux
PYTHONUTF8=1 python app.pyKhông cần thay đổi code, và nó bao phủ console, chuyển hướng và file trong lần chạy đó. Nếu bạn không muốn đặt biến mỗi lần, python - cho kết quả tương tự từ dòng lệnh.
Còn có PYTHONIOENCODING=utf-, chỉ ghi đè encoding của stdin, stdout và stderr. Hãy đọc mục tài liệu của nó trước khi dựa vào nó trên Windows: từ Python 3.6 nó bị bỏ qua với buffer console tương tác trừ khi PYTHONLEGACYWINDOWSSTDIO được đặt. File và pipe bị chuyển hướng không bị ảnh hưởng bởi ngoại lệ đó. Vì vậy nó có thể sửa python app. mà vẫn không làm gì trong cửa sổ console. Với stderr, error handler luôn là backslashreplace.
Cách sửa 2: cấu hình lại stdout trong script#
Nếu bạn không thể kiểm soát cách mọi người khởi động script, hãy thay đổi chính luồng ở ngay đầu:
import sys
sys.stdout.reconfigure(encoding="utf-8")
sys.stderr.reconfigure(encoding="utf-8")
print(reply)reconfigure được ghi tài liệu cho io.TextIOWrapper (thêm từ 3.7). Khi bạn truyền encoding và bỏ errors, handler là strict, nên một ký tự không vừa vẫn raise; với trường hợp phổ biến là UTF-8 thì không còn gì sót lại. Hai chi tiết từ tài liệu: encoding không thể thay đổi sau khi dữ liệu đã được đọc từ luồng (có thể sau khi ghi), và encoding="locale" được hỗ trợ từ 3.11.
Cần script không bao giờ crash, kể cả trên terminal thực sự không thể hiển thị văn bản? Thêm errors="replace". Các ký tự không xác định sau đó xuất hiện dưới dạng ? thay vì dừng lần chạy. Điều đó che giấu vấn đề thay vì sửa nó, nên hãy giữ nó cho log.
Cách sửa 3: cho file một encoding tường minh#
Lưu câu trả lời là cùng một lỗi, chỉ kín đáo hơn trong code:
# 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)Dùng cùng encoding="utf-8" khi bạn đọc lại file, nếu không văn bản có thể hỏng trên đường vào thay vào đó.

Bạn nên dùng cách sửa nào?#
Chọn trường hợp của bạn
Chọn trường hợp của bạn
Chọn một tùy chọn để xem đáp án
Tôi chạy script của mình trong terminal
Đặt PYTHONUTF8=1 một lần trong môi trường của bạn, hoặc khởi động với python -. Không có gì trong code thay đổi.
Tôi gửi script cho người khác
Đặt sys. ở đầu, để nó hoạt động dù họ khởi chạy thế nào.
Crash xảy ra trên file, không phải trên màn hình
Thêm encoding="utf-8" vào open(), cho cả ghi và đọc.
Bạn có thể kết hợp chúng. Một script vừa in vừa lưu câu trả lời cần Cách sửa 2 hoặc Cách sửa 1 cho màn hình và Cách sửa 3 cho file.
Nếu vẫn thất bại#
- Lỗi chuyển sang dòng khác. Thì lệnh gọi thất bại là một
printhoặcwritekhác; cách sửa phải áp dụng trước khi nó chạy, nên hãy đặtreconfigureở ngay đầu. - Lỗi nhắc đến
PYTHONUTF8. Biến có giá trị khác1hoặc0. Xóa nó và đặt lại. - Không crash, nhưng bạn thấy ô vuông hoặc
?trong console. Python đã ghi UTF-8 hợp lệ; font hoặc code page của console không thể hiển thị nó. Chuyển hướng ra file và mở file trong editor để xác nhận câu trả lời còn nguyên vẹn. - Lỗi là
JSONDecodeError, không phảiUnicodeEncodeError. Vấn đề khác: xem cách trích xuất JSON từ câu trả lời của mô hình.
Code yêu cầu ở trên là lệnh gọi requests đơn giản; tài liệu CheapTokens cho thấy cùng lệnh gọi đó với OpenAI SDK. Một mô hình khác hoạt động với cùng cách sửa: đổi trường model thành zai- (tối đa 8.192 token đầu ra mỗi câu trả lời, ngữ cảnh 390K). Lỗi encoding không liên quan gì đến mô hình, chỉ liên quan đến nơi văn bản đi tới.



