Python UnicodeDecodeError: charmap codec can't decode byte hatası çözümü
Python dosya okuma hatasında gerçek encoding değerini bulun; UTF-8, UTF-8 BOM ve Windows-1254 farklarını veri kaybetmeden uygulayın.
Python'da metin dosyası okurken UnicodeDecodeError: 'charmap' codec can't decode byte hatası, dosyanın baytlarının seçilen karakter kodlamasıyla metne çevrilemediğini gösterir. Bu hata özellikle platformun varsayılan kodlamasına güvenilen kodlarda ortaya çıkabilir.
Kalıcı çözüm, dosyanın gerçek kodlamasını öğrenip okuma sırasında açıkça belirtmektir. Dosyanın UTF-8 olduğunu doğruladıysanız encoding="utf-8" kullanın. Her dosyaya UTF-8 yazmak ise tek başına çözüm değildir; eski Windows dosyaları başka kodlamalar kullanabilir.
Decode ve encode hatası arasındaki fark
Decode, baytları Unicode metne dönüştürür. Encode, metni baytlara dönüştürür. Bu nedenle dosya okuma sırasındaki UnicodeDecodeError ile terminale yazdırırken görülen UnicodeEncodeError aynı aşamada oluşmaz. Hata izindeki satırı belirleyin; sadece konsol kodlamasını değiştirmek dosya okuma sorununu düzeltmeyebilir.
Hata mesajındaki codec adı ve byte konumu teşhis için değerlidir. charmap ifadesi tek başına dosyanın hangi kodlamada olduğunu söylemez. Bir baytın belirli bir tablodaki karşılığı bulunamadığını gösterir; kaynak dosyanın üretildiği sistem de incelenmelidir.
1. UTF-8 dosyayı açık kodlama ile okuyun
from pathlib import Path
text = Path("veri.txt").read_text(encoding="utf-8")
print(text)
Aynı işlem open ile:
with open("veri.txt", "r", encoding="utf-8") as stream:
text = stream.read()
Yeni oluşturduğunuz dosyaları da aynı sözleşmeyle kaydedin:
Path("sonuc.txt").write_text("İstanbul, çığ, şeker", encoding="utf-8")
Kodun kaydedildiği Python kaynak dosyasının UTF-8 olması, onun okuduğu dış dosyayı UTF-8 yapmaz. Buradaki encoding parametresi dış dosyanın baytlarını nasıl yorumlayacağınızı belirler.
2. UTF-8 BOM içeren dosyalarda utf-8-sig
Bazı araçlar UTF-8 dosyanın başına BOM ekler. Düz utf-8 okuması bunu \ufeff karakteri olarak koruyabilir; CSV'nin ilk kolon adı beklenmedik biçimde değişebilir. utf-8-sig başlangıçtaki UTF-8 BOM'u kaldırarak okur.
import csv
with open("liste.csv", encoding="utf-8-sig", newline="") as stream:
reader = csv.DictReader(stream)
for row in reader:
print(row)
Bu seçenek UTF-16 veya Windows-1254 dosyayı UTF-8'e dönüştürmez. Dosyanın ilk baytları FF FE veya FE FF ise UTF-16 ihtimali ayrıca değerlendirilmelidir.
3. Eski Türkçe Windows dosyalarında cp1254
Dosyayı üreten uygulama Windows-1254 kullandığını bildiriyorsa Python'daki codec adı cp1254 olabilir. Bilinen kodlamayı okuyup yeni bir UTF-8 dosyası oluşturabilirsiniz:
from pathlib import Path
source = Path("eski.txt")
text = source.read_text(encoding="cp1254")
Path("yeni-utf8.txt").write_text(text, encoding="utf-8")
Orijinal dosyayı koruyun. Çıktıda özellikle İ, ı, Ş, ş, Ğ, ğ karakterlerini ve birkaç gerçek kaydı karşılaştırın. Bir decoder'ın hata vermemesi, doğru metin ürettiğini kanıtlamaz. Yanlış bir tek baytlı kodlama bütün baytları kabul edip anlamsız karakterler oluşturabilir.
4. Encoding bilinmiyorsa baytları ve kaynağı inceleyin
raw = Path("veri.txt").read_bytes()
print(raw[:16].hex())
Dosyayı hangi uygulamanın hangi export ayarıyla ürettiğini öğrenmek en güvenilir yoldur. BOM, format tanımı veya üretici bilgisi yardımcı olur. Kodlama tahmin araçları olasılık üretir; kısa metinde ve benzer kodlamalarda kesin sonuç vermeyebilir. Dosya gerçekte PDF, görsel veya ZIP ise onu metin dosyası olarak decode etmeyin.
errors=ignore neden son çözüm değildir?
errors="ignore" çözülemeyen baytları atar. Müşteri adı, adres, ürün kodu veya muhasebe verisinde kayıp oluşabilir. errors="replace" ise yerine özel karakter koyar; kayıt tutarak bozuk veriyi göstermek için kullanılabilir, fakat kayıp karakteri geri getirmez.
Veri aktarımı işinde varsayılan katı davranışı koruyun. Okunan metni seçilen kodlamayla tekrar bayta çevirmek teknik bir tutarlılık kontrolü sağlar; gerçek kodlamayı kanıtlamak için yine kaynak bilgi ve karakter karşılaştırması gerekir. Dosya içinde karışık kodlamalar varsa üretici tarafında düzeltme veya kayıt bazında ayrıştırma gerekebilir.
Kısa rehber
Sık yapılan hata
Sırayla farklı encoding değerleri deneyip ilk hata vermeyen sonucu doğru kabul etmek. Sonuç okunabilir ve kaynakla tutarlı olmalıdır.