Python UnicodeDecodeError: “utf-8” codec can’t decode byte hatası, bir dosyanın içindeki baytlar UTF-8 kurallarına göre metne dönüştürülmeye çalışılırken geçersiz bir diziyle karşılaşıldığında ortaya çıkar. Dosya başka bir kodlamayla kaydedilmiş olabilir veya okuma sırasında kullanılan encoding değeri dosyanın gerçek kodlamasıyla uyuşmayabilir.
Hatanın temel nedeni, dosyadaki verinin bozuk olması kadar, doğru kodlama bilinmeden UTF-8 varsayımının yapılmasıdır. Bu yüzden çözüm için hata mesajındaki codec, byte ve position alanlarını anlamak gerekir.
UnicodeDecodeError hatası neden oluşur?
Bayt, bilgisayarda ikili veri olarak tutulan ve 0 ile 255 arasında değer alabilen temel veri birimidir. Karakter seti, bir metinde hangi karakterlerin ve sembollerin temsil edildiğini belirleyen yapıdır. Metin kodlaması ise karakterlerin bayt dizilerine, bayt dizilerinin de karakterlere nasıl dönüştürüleceğini tanımlar.
Python bir dosyayı okurken baytları karakterlere çevirmek için bir codec kullanır. Hata mesajındaki utf-8 codec bölümü, Python’ın veriyi UTF-8 kurallarına göre çözmeye çalıştığını gösterir. Dosyada bulunan bayt dizisi bu kurallara uymadığında UnicodeDecodeError oluşur.
veri = "Türkçe karakter".encode("cp1254")
try:
metin = veri.decode("utf-8")
except UnicodeDecodeError as hata:
print(type(hata).__name__)
Bu örnekte veri cp1254 ile baytlara dönüştürülür, ardından UTF-8 olarak çözülmeye çalışılır. İki kodlamanın kuralları uyuşmadığı için çıktı UnicodeDecodeError olur.
Mesajdaki byte alanı, Python’ın UTF-8 akışı içinde sorunlu bulduğu baytı belirtir. position alanı ise sorunun çözümlenen bayt dizisinin hangi konumunda bulunduğunu gösterir. Bu değer karakter sırasını ifade etmez; bayt dizisindeki konumu belirtir ve Python hata konumlarını genellikle sıfırdan başlayan sırayla gösterir.
Bir Türkçe karakter, kullanılan kodlamaya göre bir veya birden fazla baytla temsil edilebilir. Bu nedenle dosyayı metin olarak açmadan önce hangi kodlamayla kaydedildiğini bilmek önemlidir. open() ile okuma yaparken verilen encoding değeri dosyanın gerçek kodlamasıyla eşleştiğinde çözümleme doğru gerçekleşir.
UTF-8, cp1254 ve ISO-8859-9 nasıl ayrılır?

UTF-8, Unicode karakterlerini değişken uzunluklu bayt dizileriyle kodlayan bir yöntemdir. Bir karakter tek baytla temsil edilebildiği gibi, karaktere bağlı olarak birden fazla baytla da temsil edilebilir.
cp1254 ve ISO-8859-9 ise Türkçe karakterleri destekleyen tek baytlı kodlamalardır. Bu kodlamalarda her karakter bir baytla temsil edilir. Karakterlerin ortak olması, bu karakterlerin bütün bayt karşılıklarının aynı olduğu anlamına gelmez. Bazı bayt değerleri cp1254 ve ISO-8859-9 içinde farklı karakterler olarak yorumlanabilir.
Karakter seti ile kodlama arasındaki fark burada önem kazanır. Karakter seti kullanılabilecek karakterleri tanımlarken kodlama, bu karakterlerin dosyada hangi baytlarla saklanacağını belirler. Dosyada Türkçe karakterlerin bulunması, dosyanın hangi kodlamayla oluşturulduğunu tek başına göstermez.
Yanlış kodlama her zaman hata üretmeyebilir. Bazı bayt dizileri farklı bir kodlamada da geçerli kabul edilebilir ve bu durumda Python metni okur, ancak karakterler yanlış görünebilir. Bu nedenle yalnızca UnicodeDecodeError alınıp alınmadığına bakmak yerine, okunan metnin Türkçe karakterleri doğru gösterip göstermediği de kontrol edilmelidir.
CSV dosyası doğru kodlamayla nasıl okunur?

CSV dosyasını okurken kullanılan encoding değeri, dosyanın gerçekten kaydedildiği kodlamayla aynı olmalıdır. Kodlama, karakterlerin baytlara ve baytların tekrar karakterlere dönüştürülme kuralıdır. Bayt ise dosyada saklanan ham sayısal veridir; Python bu baytları seçtiğin kodlamaya göre metne çevirmeye çalışır.
Aşağıdaki örnekte Türkçe karakterler içeren CSV dosyası özellikle cp1254 kodlamasıyla oluşturuluyor. Ardından dosya önce yanlış biçimde UTF-8 olarak okunuyor, sonra doğru kodlamayla tekrar açılıyor.
import csv
with open("ornek.csv", "w", encoding="cp1254", newline="") as dosya:
dosya.write("şehir,öğrencin")
dosya.write("İzmir,Çağrın")
try:
with open("ornek.csv", "r", encoding="utf-8", newline="") as dosya:
satirlar = list(csv.reader(dosya))
except UnicodeDecodeError:
print("UTF-8 ile okuma başarısız.")
with open("ornek.csv", "r", encoding="cp1254", newline="") as dosya:
for satir in csv.reader(dosya):
print(satir)
Bu kodun çıktısında önce UTF-8 ile okuma başarısız. mesajı görülür. Doğru kodlamayla yapılan ikinci okumada ise ['şehir', 'öğrenci'] ve ['İzmir', 'Çağrı'] satırları yazdırılır. Hata mesajındaki bayt ve konum bilgileri dosyanın içeriğine ve kullanılan Python ortamına bağlı olduğu için örnekte ayrıca gösterilmemiştir.
Buradaki cp1254 seçimi yalnızca dosyanın aynı kodlamayla oluşturulduğu bilindiği için doğrudur. Bir CSV dosyasını okurken bu değeri varsayılan çözüm olarak kullanma; Excel veya eski Windows dışa aktarımlarında kullanılan kodlama dosyanın kayıt ayarlarına göre değişebilir. Python dosya işlemleriyle ilgili temel bilgilerini ölçmek için Python bilgi testini de kullanabilirsin.
Dosyanın kodlaması nasıl belirlenir?
Dosyanın kodlamasını belirlemenin en güvenilir başlangıç noktası, dosyayı oluşturan veya dışa aktaran programın kayıt ayarlarını kontrol etmektir. Dışa aktarma ekranında kodlama seçimi bulunuyorsa bu bilgiyi not et, ardından dosyayı bir metin düzenleyicide açarak düzenleyicinin gösterdiği kodlamayla karşılaştır.
Kaynak program bilgi vermiyorsa dosyanın sağlandığı kişi, kurum veya sistemin belgeleri incelenmelidir. Ardından dosyadaki Türkçe karakterleri, sütun ayrımlarını ve metnin anlamını kontrol ederek okuma sonucunu doğrula. Bir kodlama dosyayı hatasız açsa bile karakterler bozulmuş olabilir; örneğin Türkçe harflerin yerine farklı semboller geliyorsa seçim doğru değildir.
Rastgele biçimde utf-8, cp1254 ve iso-8859-9 denemek hızlı görünebilir, ancak her zaman güvenilir sonuç vermez. Bazı dosyalarda yalnızca temel Latin karakterleri bulunur ve birden fazla kodlama aynı metni doğru gösterir. Bu nedenle kodlama kararını hata alınmamasına değil, dosyanın bilinen içeriğiyle tutarlı sonuç elde edilmesine dayandır.
Kodlama tespit araçları da dosyadaki bayt örüntülerinden hareketle tahmin üretir. Sonucu kesin bilgi olarak kabul etmek yerine, tahmini dosyanın kaynağı ve metin içeriğiyle karşılaştır. Python'un metin akışları ve varsayılan kodlama belgeleri de dosya açarken kodlamayı açıkça belirtmenin neden önemli olduğunu açıklar.
Hata seçenekleri ve UTF-8'e dönüştürme
errors="replace", çözümlenemeyen baytları yer tutucu karakterlerle değiştirir. errors="ignore" ise bu baytları atlar. Her iki seçenek de dosyanın özgün bilgisini kaybettirebileceği için veri temizleme amacıyla dikkatli kullanılmalıdır.
Kaynak kodlamasını doğruladıktan sonra dosyayı okuyup UTF-8 olarak ayrı bir dosyaya yazabilirsin. Aşağıdaki örnekte kaynak dosya cp1254 ile oluşturuluyor, ardından aynı metin UTF-8 olarak kaydediliyor:
from pathlib import Path
Path("kaynak.txt").write_text(
"İzmir'de Türkçe karakterler: ç, ğ, ı, ö, ş, ü.",
encoding="cp1254"
)
metin = Path("kaynak.txt").read_text(encoding="cp1254")
Path("hedef.txt").write_text(metin, encoding="utf-8")
print(Path("hedef.txt").read_text(encoding="utf-8"))
Programın çıktısı İzmir'de Türkçe karakterler: ç, ğ, ı, ö, ş, ü. olur. Okuma ve yazma işlemlerinde kodlamayı ayrı ayrı belirtmek, dönüşümün hangi aşamada yapıldığını açıkça gösterir. Yanlış kaynak kodlaması seçilirse bozuk karakterler UTF-8 dosyasına da aktarılır ve hatalı içerik kalıcı hâle gelebilir. Bu nedenle özgün dosyayı koruyup yeni dosyanın içeriğini kontrol etmelisin. Dosya işlemlerinin temelini pekiştirmek için ücretsiz Python video eğitimi içindeki örneklerden yararlanabilirsin.
Sık Sorulan Sorular
Dosyayı cp1254 ile açmak her Türkçe karakter sorununu çözer mi?
Hayır, cp1254 yalnızca dosya gerçekten bu kodlamayla oluşturulduysa doğru sonuç verir. Kaynak dosya UTF-8, ISO-8859-9 veya başka bir kodlama kullanıyorsa farklı karakterler oluşabilir.
errors="ignore" kullanmak neden risklidir?
errors="ignore", çözümlenemeyen baytları sessizce atladığı için kelimelerin, ayraçların veya önemli veri parçalarının eksilmesine yol açabilir.
Dosya hatasız açıldığı hâlde Türkçe karakterler neden bozuk görünür?
Dosya hatasız açılabilir, çünkü seçilen kodlama baytları geçerli karakterlere dönüştürmüş olabilir. Ancak seçilen kodlama yanlışsa bu karakterler ekranda bozuk veya anlamsız görünebilir.
Kodlamayı doğrulayarak okumak, UTF-8 çıktıyı ayrı dosyaya yazmak ve sonucu özgün içerikle karşılaştırmak güvenli bir dönüşüm süreci sağlar.