การแก้ไขปัญหาคู่มือ
UnicodeEncodeError เมื่อพิมพ์คำตอบ LLM ใน Python: 3 วิธีแก้
print(reply) แครชบนอักษรซีริลลิกหรืออีโมจิ? ดูว่าทำไม Python ล้มเหลวกับเอาต์พุตที่ถูกเปลี่ยนเส้นทางหรือโค้ดเพจแบบเก่า และแก้ด้วยโหมด UTF-8, reconfigure หรือ encoding=

ในหน้านี้
คำขอของคุณผ่านไป โมเดลตอบกลับ แล้วจากนั้น Python ก็พังที่ print(reply) API ไม่ใช่ต้นเหตุ คำตอบนั้นปกติดี แต่ที่ที่คุณพิมพ์มันออกมาไม่สามารถแสดงอักขระบางตัวได้ วิธีแก้ที่เร็วที่สุดคือเปิดโหมด UTF-8 ด้วย PYTHONUTF8=1 ถ้าคุณอยากเก็บไว้ในสคริปต์ ให้เรียก sys. ที่ด้านบน และเมื่อคุณบันทึกคำตอบลงไฟล์ ให้ส่ง encoding="utf-8" ให้ open()
ข้อผิดพลาดมีหน้าตาอย่างไร#
สมมติคุณถามโมเดลเป็นภาษารัสเซียแล้วพิมพ์คำตอบ นี่คือสคริปต์ทั้งหมด โดยใช้ การเรียก requests แบบธรรมดาจากคู่มือคำขอแรกของเรา:
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)เมื่อ stdout ถูกเปลี่ยนเส้นทางไปยังไฟล์หรือไปป์ หรือ Python ถูกเริ่มด้วยโค้ดเพจแบบเก่าสำหรับสตรีม บรรทัดสุดท้ายจะจบแบบนี้:
UnicodeEncodeError: 'charmap' codec can't encode characters in position 0-5: character maps to <undefined>ชื่อ codec ในข้อความของคุณขึ้นอยู่กับการเข้ารหัสของสตรีม (สำหรับโค้ดเพจ Windows มักเป็น charmap สำหรับ ascii คือ ascii) และตำแหน่งขึ้นอยู่กับคำตอบ รูปแบบเหมือนเดิมเสมอ: traceback ชี้ไปที่ print ไม่ใช่ที่คำขอ

ทำไมถึงเกิดขึ้น? print แปลงข้อความเป็นไบต์โดยใช้การเข้ารหัสของ sys.stdout ถ้าการเข้ารหัสนั้นเป็นโค้ดเพจแบบเก่า อักขระใดๆ ที่อยู่นอกเหนือจากนั้น เช่น อักษรซีริลลิกในโค้ดเพจตะวันตก อีโมจิ บางครั้งขีดกลางแบบตัวพิมพ์ จะไม่มีไบต์ให้แปลง Python จึงโยนข้อผิดพลาดแทนที่จะเดา
มันปรากฏในสามสถานการณ์:
- stdout ถูกเปลี่ยนเส้นทางหรือไปป์ (
python app.,py > out. txt | another program) หรือสคริปต์รันจากตัวจัดตารางเวลา CI หรือเอดิเตอร์ที่ stdout ไม่ใช่คอนโซล PYTHONLEGACYWINDOWSSTDIOถูกตั้งค่า หรือสตรีมได้รับการเข้ารหัสแบบแคบด้วยเหตุอื่น- คุณเขียนคำตอบลงไฟล์ด้วย
open(path, "w")โดยไม่มีencoding=
Python ตัวไหน? ทุกอย่างด้านล่างนี้เกี่ยวกับ Python 3.7–3.14 ซึ่งการเข้ารหัสของสตรีมและไฟล์มาจากระบบ ตาม PEP 686 (สถานะ Final ตรวจสอบ https://peps.python.org/pep-0686/, เมื่อ 5 พฤศจิกายน 2026) โหมด UTF-8 เปิดเป็นค่าเริ่มต้นตั้งแต่ Python 3.15 ดังนั้น open() และ stdio ใช้ UTF-8 อยู่แล้วที่นั่น เว้นแต่มีคนปิดด้วย PYTHONUTF8=0 หรือ -X utf8=0 ตรวจสอบด้วย python --version
ตรวจสอบว่าคุณมีการเข้ารหัสอะไรจริงๆ#
ก่อนที่คุณจะเปลี่ยนอะไร ให้ดูว่า Python เลือกอะไร ใช้เวลาสิบวินาที
ลองด้วยตัวเองลองดู: Python คิดว่าการเข้ารหัส stdout ของคุณคืออะไร?แสดงคำตอบ
รัน python - ในหน้าต่างเดียวกับที่สคริปต์ล้มเหลว ในคอนโซลแบบอินเทอร์แอกทีฟมักพิมพ์ utf-8 ดังนั้นแค่นั้นพิสูจน์อะไรได้น้อย รันอีกครั้งโดยเติม > check.txt ต่อท้ายแล้วเปิดไฟล์: เอาต์พุตที่ถูกเปลี่ยนเส้นทางคือสิ่งที่มักให้ชื่อ cp… หรือ ascii และนั่นคือตัวการของคุณ ถ้าทุกอย่างบอกว่า utf-8 ให้ดูไฟล์ที่คุณเขียนลงไป
อยากเห็นการแครชโดยไม่ต้องรอวันแย่ๆ? บน macOS หรือ Linux บังคับการเข้ารหัสแบบแคบสำหรับการรันหนึ่งครั้ง:
PYTHONIOENCODING=ascii python -c "print('Привет')"มันล้มเหลวด้วยข้อความ codec ascii ซึ่งอยู่ในตระกูลเดียวกับข้อผิดพลาดข้างต้น บน Windows ตัวแปรนี้ถูกเพิกเฉยสำหรับคอนโซลแบบอินเทอร์แอกทีฟ แต่จะทำงานเมื่อเอาต์พุตถูกเปลี่ยนเส้นทาง: ใน cmd รัน set PYTHONIOENCODING=ascii แล้ว python - (ใน PowerShell: $env:PYTHONIOENCODING = "ascii")
วิธีแก้ 1: เปิดโหมด UTF-8#
Python มีโหมดที่ทำให้ UTF-8 เป็นค่าเริ่มต้นสำหรับข้อความ ตามเอกสาร Python (หน้าบรรทัดคำสั่ง ตรวจสอบ 5 พฤศจิกายน 2026) PYTHONUTF8=1 เปิดมันและ -X utf8 ทำเช่นเดียวกัน ทั้งคู่มีตั้งแต่ Python 3.7 ข้อควรระวังจากหน้าเดียวกัน: ค่าอื่นที่ไม่ว่างเปล่าของ PYTHONUTF8 ทำให้เกิดข้อผิดพลาดตอนเริ่มต้น ดังนั้นใช้ 1 เป๊ะๆ (หรือ 0 เพื่อปิด) บน 3.15 คุณต้องการสิ่งนี้เพียงเพื่อเปิดโหมดอย่างชัดเจนบนอินเทอร์พรีเตอร์รุ่นเก่า ถ้ามันเปิดอยู่แล้วที่นั่น ให้มองหา PYTHONUTF8=0 ในสภาพแวดล้อมของคุณ
เปิดโหมด UTF-8 สำหรับการรันหนึ่งครั้ง
cmd
set PYTHONUTF8=1
python app.pyPowerShell
$env:PYTHONUTF8 = "1"
python app.pymacOS / Linux
PYTHONUTF8=1 python app.pyไม่ต้องแก้โค้ด และครอบคลุมคอนโซล การเปลี่ยนเส้นทาง และไฟล์ในการรันนั้น ถ้าคุณไม่อยากตั้งตัวแปรทุกครั้ง python - ให้ผลลัพธ์เดียวกันจากบรรทัดคำสั่ง
ยังมี PYTHONIOENCODING=utf- ซึ่งเขียนทับการเข้ารหัสของ stdin, stdout และ stderr เท่านั้น อ่านรายการเอกสารของมันก่อนที่คุณจะพึ่งพามันบน Windows: ตั้งแต่ Python 3.6 มันถูกเพิกเฉยสำหรับบัฟเฟอร์คอนโซลแบบอินเทอร์แอกทีฟ เว้นแต่ PYTHONLEGACYWINDOWSSTDIO ถูกตั้งค่า ไฟล์และไปป์ที่ถูกเปลี่ยนเส้นทางไม่ได้รับผลกระทบจากข้อยกเว้นนั้น ดังนั้นมันสามารถแก้ python app. และยังไม่ทำอะไรในหน้าต่างคอนโซล สำหรับ stderr ตัวจัดการข้อผิดพลาดจะเป็น backslashreplace เสมอ
วิธีแก้ 2: กำหนดค่า stdout ใหม่ภายในสคริปต์#
ถ้าคุณควบคุมวิธีที่ผู้คนเริ่มสคริปต์ไม่ได้ ให้เปลี่ยนสตรีมเองที่ด้านบนสุด:
import sys
sys.stdout.reconfigure(encoding="utf-8")
sys.stderr.reconfigure(encoding="utf-8")
print(reply)reconfigure มีเอกสารสำหรับ io.TextIOWrapper (เพิ่มใน 3.7) เมื่อคุณส่ง encoding และละ errors ตัวจัดการจะเป็น strict ดังนั้นอักขระที่ไม่พอดีจะยังคงโยนข้อผิดพลาด สำหรับกรณีทั่วไปของ UTF-8 ไม่มีอะไรเหลือค้าง สองรายละเอียดจากเอกสาร: การเข้ารหัสไม่สามารถเปลี่ยนได้เมื่ออ่านข้อมูลจากสตรีมแล้ว (เปลี่ยนได้หลังการเขียน) และ encoding="locale" รองรับตั้งแต่ 3.11
ต้องการให้สคริปต์ไม่แครชเลย แม้บนเทอร์มินัลที่ไม่สามารถแสดงข้อความได้จริงๆ? เพิ่ม errors="replace" อักขระที่ไม่รู้จักจะปรากฏเป็น ? แทนที่จะหยุดการรัน นั่นซ่อนปัญหาแทนที่จะแก้ไข ดังนั้นเก็บไว้สำหรับบันทึก
วิธีแก้ 3: ให้ไฟล์มีการเข้ารหัสที่ชัดเจน#
การบันทึกคำตอบคือความล้มเหลวเดียวกัน เพียงแต่เงียบกว่าในโค้ด:
# 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)ใช้ encoding="utf-8" เดียวกันเมื่อคุณอ่านไฟล์กลับ มิฉะนั้นข้อความอาจเสียหายตอนนำเข้าแทน

ควรใช้วิธีแก้ไหน?#
เลือกกรณีของคุณ
เลือกกรณีของคุณ
เลือกตัวเลือกเพื่อดูคำตอบ
ฉันรันสคริปต์ของตัวเองในเทอร์มินัล
ตั้ง PYTHONUTF8=1 ครั้งเดียวในสภาพแวดล้อมของคุณ หรือเริ่มด้วย python - ไม่มีอะไรในโค้ดเปลี่ยน
ฉันส่งสคริปต์ให้คนอื่น
ใส่ sys. ที่ด้านบน เพื่อให้ทำงานได้ไม่ว่าพวกเขาจะเปิดมันอย่างไร
การแครชอยู่ที่ไฟล์ ไม่ใช่บนหน้าจอ
เพิ่ม encoding="utf-8" ให้ open() สำหรับการเขียนและการอ่าน
คุณสามารถรวม它们ได้ สคริปต์ที่พิมพ์และบันทึกคำตอบต้องการวิธีแก้ 2 หรือวิธีแก้ 1 สำหรับหน้าจอ และวิธีแก้ 3 สำหรับไฟล์
ถ้ามันยังล้มเหลว#
- ข้อผิดพลาดย้ายไปบรรทัดอื่น แสดงว่าการเรียกที่ล้มเหลวคือ
printหรือwriteอีกตัว วิธีแก้ต้องใช้ก่อนที่มันจะรัน ดังนั้นใส่reconfigureที่ด้านบนสุด - ข้อผิดพลาดกล่าวถึง
PYTHONUTF8ตัวแปรมีค่าอื่นที่ไม่ใช่1หรือ0ลบมันออกแล้วตั้งใหม่ - ไม่แครช แต่คุณเห็นสี่เหลี่ยมหรือ
?ในคอนโซล Python เขียน UTF-8 ที่ถูกต้อง ฟอนต์หรือโค้ดเพจของคอนโซลไม่สามารถแสดงได้ เปลี่ยนเส้นทางไปยังไฟล์แล้วเปิดไฟล์ในเอดิเตอร์เพื่อยืนยันว่าคำตอบสมบูรณ์ - ข้อผิดพลาดเป็น
JSONDecodeErrorไม่ใช่UnicodeEncodeErrorปัญหาต่างกัน: ดู วิธีแยก JSON จากคำตอบของโมเดล
โค้ดคำขอข้างต้นคือการเรียก requests แบบธรรมดา เอกสาร CheapTokens แสดงการเรียกเดียวกันสำหรับ OpenAI SDK โมเดลอื่นทำงานได้กับวิธีแก้เดียวกัน: เปลี่ยนฟิลด์ model เป็น zai- (สูงสุด 8,192 โทเค็นเอาต์พุตต่อคำตอบ บริบท 390K) ข้อผิดพลาดการเข้ารหัสไม่เกี่ยวข้องกับโมเดล เกี่ยวข้องกับที่ที่ข้อความไปเท่านั้น



