Bloga dön

Sorun gidermeKılavuz

Python'da bir LLM yanıtını yazdırırken UnicodeEncodeError: 3 çözüm

print(reply) Kiril harflerinde veya emojide çöküyor mu? Python'un yönlendirilmiş çıktıda veya eski bir kod sayfasında neden başarısız olduğunu görün ve UTF-8 modu, reconfigure veya encoding= ile düzeltin.

Yazan: CheapTokens TeamYayınlanma tarihi: 5 dk okuma

print(reply) üzerinde UnicodeEncodeError ve UTF-8 düzeltmesi, hata kartı olarak çizilmiş
Bu sayfada
  1. Hata nasıl görünür
  2. Gerçekte hangi kodlamaya sahip olduğunuzu kontrol edin
  3. Çözüm 1: UTF-8 modunu açın
  4. Çözüm 2: betik içinde stdout'u yeniden yapılandırın
  5. Çözüm 3: dosyalara açık bir kodlama verin
  6. Hangi çözümü kullanmalısınız?
  7. Hâlâ başarısız olursa

İsteğiniz geçti, model yanıtladı ve sonra Python print(reply) üzerinde çöktü. Sorun API'de değil. Yanıt sorunsuz; onu yazdırdığınız yer bazı karakterlerini temsil edemiyor. En hızlı çözüm, UTF-8 modunu PYTHONUTF8=1 ile açmaktır. Bunu betiğin içinde tutmayı tercih ederseniz, en üstte sys.stdout.reconfigure(encoding="utf-8") çağırın ve bir yanıtı dosyaya kaydederken open()'e encoding="utf-8" geçirin.

Hata nasıl görünür#

Bir modele Rusça bir soru sorduğunuzu ve yanıtı yazdırdığınızı varsayalım. Bu, ilk istek rehberimizdeki düz requests çağrısını kullanan betiğin tamamıdır:

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)

stdout bir dosyaya veya boruya yönlendirildiğinde ya da Python akışları için eski bir kod sayfasıyla başlatıldığında, son satır şöyle biter:

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

Mesajınızdaki codec adı akışın kodlamasına bağlıdır (bir Windows kod sayfası için genellikle charmap, ascii için ascii), konumlar ise yanıta bağlıdır. Şekil her zaman aynıdır: izleme (traceback) isteğe değil, print'e işaret eder.

print(reply) satırına işaret eden bir UnicodeEncodeError izlemesi
Hatanın tipik şekli: API çağrısı zaten başarılı olduktan sonra print tarafından fırlatılır

Neden olur? print, metni sys.stdout kodlamasını kullanarak baytlara dönüştürür. Bu kodlama eski bir kod sayfasıysa, onun dışında kalan her karakterin (Batı kod sayfasındaki Kiril harfleri, bir emoji, bazen tipografik bir tire) dönüştürüleceği bir bayt yoktur. Python tahmin etmek yerine hata fırlatır.

Üç durumda ortaya çıkar:

  • stdout yönlendirilmiş veya boruya bağlanmıştır (python app.py > out.txt, | another program) ya da betik stdout'un konsol olmadığı bir zamanlayıcıdan, CI'dan veya editörden çalışır;
  • PYTHONLEGACYWINDOWSSTDIO ayarlanmıştır ya da akış başka bir şekilde dar bir kodlama alır;
  • yanıtı open(path, "w") ile ve encoding= olmadan bir dosyaya yazarsınız.

Hangi Python? Aşağıdakilerin tümü, akış ve dosya kodlamasının sistemden geldiği Python 3.7–3.14 hakkındadır. PEP 686'ya göre (durum Final, https://peps.python.org/pep-0686/, 5 Kasım 2026'da kontrol edildi), UTF-8 modu Python 3.15'ten itibaren varsayılan olarak açıktır, yani biri PYTHONUTF8=0 veya -X utf8=0 ile kapatmadığı sürece open() ve stdio orada zaten UTF-8 kullanır. python --version ile kontrol edin.

Gerçekte hangi kodlamaya sahip olduğunuzu kontrol edin#

Bir şeyi değiştirmeden önce Python'un ne seçtiğine bakın. On saniye sürer.

Kendin deneDeneyin: Python stdout kodlamanızın ne olduğunu düşünüyor?Cevabı göster

Betiğin başarısız olduğu aynı pencerede python -c "import sys; print(sys.stdout.encoding)" çalıştırın. Etkileşimli bir konsolda genellikle utf-8 yazdırır, yani bu tek başına pek bir şey kanıtlamaz. Sonuna > check.txt ekleyerek tekrar çalıştırın ve dosyayı açın: yönlendirilmiş çıktı, daha sık olarak bir cp… adı veya ascii veren şeydir ve suçlu da odur. Her şey utf-8 diyorsa, yazdığınız bir dosyaya bakın.

Kötü bir günü beklemeden çökmeyi görmek ister misiniz? macOS veya Linux'ta, tek bir çalıştırma için dar bir kodlama zorlayın:

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

Bu, yukarıdaki hatayla aynı aileden bir ascii codec mesajıyla başarısız olur. Windows'ta değişken etkileşimli bir konsol için yok sayılır, ancak çıktı yönlendirildiğinde çalışır: cmd'de set PYTHONIOENCODING=ascii, ardından python -c "print('Привет')" > out.txt çalıştırın (PowerShell'de: $env:PYTHONIOENCODING = "ascii").

Çözüm 1: UTF-8 modunu açın#

Python'un metin için UTF-8'i varsayılan yapan bir modu vardır. Python belgelerine göre (komut satırı sayfası, 5 Kasım 2026'da kontrol edildi), PYTHONUTF8=1 bunu açar ve -X utf8 aynısını yapar; ikisi de Python 3.7'den beri mevcuttur. Aynı sayfadan bir uyarı: PYTHONUTF8 değişkeninin boş olmayan başka herhangi bir değeri başlangıçta hataya neden olur, bu yüzden tam olarak 1 kullanın (veya kapatmak için 0). 3.15'te buna yalnızca eski yorumlayıcılarda modu açıkça etkinleştirmek için ihtiyacınız olur; orada zaten açıksa, ortamınızda PYTHONUTF8=0 arayın.

Tek bir çalıştırma için UTF-8 modunu açın

cmd

bat
set PYTHONUTF8=1
python app.py

PowerShell

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

macOS / Linux

bash
PYTHONUTF8=1 python app.py

Kod değişikliği yok ve o çalıştırmada konsolu, yönlendirmeleri ve dosyaları kapsar. Her seferinde bir değişken ayarlamak istemiyorsanız, python -X utf8 app.py komut satırından aynı sonucu verir.

Ayrıca yalnızca stdin, stdout ve stderr kodlamasını geçersiz kılan PYTHONIOENCODING=utf-8 de vardır. Windows'ta buna güvenmeden önce belgelerdeki girdisini okuyun: Python 3.6'dan beri, PYTHONLEGACYWINDOWSSTDIO ayarlanmadıkça etkileşimli bir konsol arabelleği için yok sayılır. Yönlendirilmiş dosyalar ve borular bu istisnadan etkilenmez. Yani python app.py > out.txt sorununu çözebilir ve konsol penceresinde yine hiçbir şey yapmayabilir. stderr için hata işleyici her zaman backslashreplace'dir.

Çözüm 2: betik içinde stdout'u yeniden yapılandırın#

İnsanların betiği nasıl başlattığını kontrol edemiyorsanız, akışın kendisini en üstte değiştirin:

python
import sys

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

print(reply)

reconfigure, io.TextIOWrapper için belgelenmiştir (3.7'de eklendi). encoding geçirip errors'i dışarıda bıraktığınızda işleyici strict olur, yani sığmayan bir karakter yine de hata fırlatır; UTF-8'in yaygın durumunda geriye hiçbir şey kalmaz. Belgelerden iki ayrıntı: akıştan veri okunduktan sonra kodlama değiştirilemez (bir yazmadan sonra değiştirilebilir) ve encoding="locale" 3.11'den beri desteklenir.

Betiğin, metni gerçekten gösteremeyen bir terminalde bile asla çökmemesini mi istiyorsunuz? errors="replace" ekleyin. Bilinmeyen karakterler o zaman çalıştırmayı durdurmak yerine ? olarak görünür. Bu, sorunu çözmek yerine gizler, bu yüzden bunu günlükler için saklayın.

Çözüm 3: dosyalara açık bir kodlama verin#

Bir yanıtı kaydetmek aynı hatadır, yalnızca kodda daha sessizdir:

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)

Dosyayı geri okurken de aynı encoding="utf-8" kullanın, aksi halde metin bu kez okuma sırasında bozulabilir.

Önce: print(reply) UnicodeEncodeError fırlatır. Sonra: aynı satır yanıtın tamamını yazdırır
Aynı print satırı, UTF-8 modundan önce ve sonra

Hangi çözümü kullanmalısınız?#

Durumunu seç

Durumunuzu seçin

Betiğimi bir terminalde kendim çalıştırıyorum

Ortamınızda bir kez PYTHONUTF8=1 ayarlayın veya python -X utf8 app.py ile başlatın. Kodda hiçbir şey değişmez.

Betiği başkalarına dağıtıyorum

En üste sys.stdout.reconfigure(encoding="utf-8") koyun, böylece nasıl başlatırlarsa başlatsınlar çalışır.

Çökme ekranda değil, bir dosyada

Yazma ve okuma için open()'e encoding="utf-8" ekleyin.

Bunları birleştirebilirsiniz. Yanıtları yazdıran ve kaydeden bir betik, ekran için Çözüm 2 veya Çözüm 1'e ve dosya için Çözüm 3'e ihtiyaç duyar.

Hâlâ başarısız olursa#

  • Hata farklı bir satıra taşındı. O zaman başarısız olan çağrı başka bir print veya write'dir; düzeltme ondan önce uygulanmalıdır, bu yüzden reconfigure'i en üste koyun.
  • Hata PYTHONUTF8'den söz ediyor. Değişkenin 1 veya 0 dışında bir değeri var. Kaldırın ve yeniden ayarlayın.
  • Çökme yok, ama konsolda kareler veya ? görüyorsunuz. Python geçerli UTF-8 yazdı; konsol yazı tipi veya kod sayfası bunu gösteremiyor. Bir dosyaya yönlendirin ve yanıtın bozulmadığını doğrulamak için dosyayı bir editörde açın.
  • Hata UnicodeEncodeError değil, JSONDecodeError. Farklı bir sorun: bir model yanıtından JSON nasıl çıkarılır bölümüne bakın.

Yukarıdaki istek kodu düz requests çağrısıdır; CheapTokens belgeleri aynı çağrıyı OpenAI SDK için gösterir. Başka bir model de aynı düzeltmeyle çalışır: model alanını zai-org/GLM-5.3-Flash ile değiştirin (yanıt başına 8.192 çıktı token'ına kadar, 390K bağlam). Kodlama hatasının modelle hiçbir ilgisi yoktur, yalnızca metnin nereye gittiğiyle ilgilidir.