Python'da JSON: dosya okuma ve yazma, CSV, pathlib ve UTF-8 kodlaması
Python'da JSON için yerleşik json modülü kullanılır: json.load açık bir dosyadan veri okur, json.dump dosyaya yazar, json.loads ve json.dumps aynı işi metinlerle yapar. Dosyalar with open(yol, encoding="utf-8") ile açılır, yollar pathlib.Path ile kurulur, tablo verileri ise csv modülüyle okunur.
Python'da JSON ile çalışmak için ek bir kütüphane gerekmez: json modülü standart kütüphanenin parçasıdır ve sözlükleri, listeleri metne, metni de tekrar sözlük ve listeye çevirir. Yanında neredeyse her zaman üç şey daha gerekir: with ile birlikte kullanılan open fonksiyonu, yollar için pathlib modülü ve tablolar için csv modülü. Aşağıda hepsini çalışan kodlarla ve en sık yapılan hatalarla birlikte sırayla anlatıyoruz.
Python open fonksiyonu: modlar ve kodlama
Her metin dosyası yerleşik open(yol, mod, encoding=...) fonksiyonuyla açılır. Bu fonksiyon read, readline, write metotlarına sahip bir dosya nesnesi döndürür ve nesne döngüyle satır satır dolaşılabilir.
| Mod | Ne yapar |
|---|---|
"r" | Okuma (varsayılan). Dosya yoksa FileNotFoundError |
"w" | Yazma. Dosya oluşturulur ya da açılır açılmaz içeriği silinir |
"a" | Sona ekleme, mevcut içerik korunur |
"x" | Yeni dosya oluşturma; dosya zaten varsa FileExistsError |
"b" | Mod eki: bayt ile çalışma ("rb", "wb") |
with neden gerekli
Dosyanın kapatılması gerekir: aksi halde veriler diske yazılmayabilir ve sistem dosya tanıtıcısını meşgul görür. with bloğu dosyayı otomatik kapatır; blok içinde hata olsa bile.
with open("notlar.txt", "w", encoding="utf-8") as f:
f.write("İlk satır\n")
f.write("İkinci satır\n")
with open("notlar.txt", encoding="utf-8") as f:
for line in f:
print(line.rstrip("\n"))
Dosyayı döngüyle okumak satırları teker teker işler; tüm dosyayı belleğe yüklemez. Bu yüzden gigabayt boyutundaki günlük dosyaları da bu şekilde işleyebilirsiniz. f.read() tüm içeriği tek bir metin olarak, f.readlines() ise satırların listesini verir.
Metni dosyaya nasıl eklersiniz, eskisini silmeden
Yeni başlayanların en sık hatası, bir satır "eklemek" için dosyayı "w" modunda açmaktır. "w" dosyayı, daha ilk write çağrılmadan, açarken temizler. Sona eklemek için "a", yanlışlıkla bir dosyanın üzerine yazmamak için "x" kullanın.
with open("gunluk.txt", "a", encoding="utf-8") as f:
f.write("yeni kayıt\n")
write satır sonu eklemez; "\n" açıkça yazılmalıdır. Alternatif olarak print(..., file=f) kullanabilirsiniz: satır sonunu o koyar.
UTF-8 kodlaması: "bozuk karakterler" neden çıkar
Python 3.15'e kadar open(), encoding parametresi verilmezse sistemin kodlamasını kullanır. Linux ve macOS'ta bu UTF-8'dir, Türkçe Windows'ta ise genellikle cp1254 ya da cp1251 gibi eski bir kodlama. Sunucuda sorunsuz çalışan bir betik, bir arkadaşın bilgisayarında "Ç" gibi bozuk metin üretebilir ya da UnicodeDecodeError ile çökebilir.
Python 3.15'te PEP 686 gereği UTF-8 modu varsayılan olarak açıktır: encoding verilmeyen open() tüm işletim sistemlerinde UTF-8 okur ve yazar. Eski davranışı ortam değişkeni PYTHONUTF8=0 ya da -X utf8=0 bayrağıyla geri alabilirsiniz; sistem kodlamasını açıkça istemek için encoding="locale" kullanılır.
import sys
print(sys.flags.utf8_mode) # Python 3.15'te 1
open("eski.txt", encoding="locale") # sistem kodlaması
open("eski_excel.csv", encoding="cp1254") # cp1254 ile kaydedilmiş dosya
Ters yönde de bir risk var: Excel'den ya da Windows betiğinden gelen eski bir cp1254 CSV'si artık UTF-8 olarak okunur ve UnicodeDecodeError verir. Çözüm, dosyayı önce doğru kodlamayla okuyup UTF-8 olarak yeniden kaydetmektir. Kural değişmiyor: encoding parametresini her zaman açıkça yazın; kod her sürümde aynı davranır.
pathlib: yollar nesne olarak
Yolları metin birleştirmeyle ("veri" + "/" + ad) kurmak zahmetlidir ve işletim sistemleri arasında bozulur. pathlib modülündeki Path sınıfında yollar / operatörüyle birleşir ve nesnenin kullanışlı özellikleri vardır.
from pathlib import Path
veri = Path("veri")
csv_yolu = veri / "harcamalar.csv"
print(csv_yolu.name) # harcamalar.csv
print(csv_yolu.stem) # harcamalar
print(csv_yolu.suffix) # .csv
print(csv_yolu.parent) # veri
print(csv_yolu.exists())
veri.mkdir(parents=True, exist_ok=True)
(veri / "merhaba.txt").write_text("Merhaba", encoding="utf-8")
print((veri / "merhaba.txt").read_text(encoding="utf-8"))
for p in veri.glob("*.csv"):
print(p)
read_text ve write_text, küçük dosyalar için open + with ikilisinin yerini alır. Path nesnesini open, json ve csv gibi tüm bu araçlara doğrudan verebilirsiniz. Yolu komutun çalıştığı klasöre değil, betiğin kendi klasörüne göre kurmak için: Path(__file__).parent / "veri".
Python 3.14'te Path nesnesine copy() ve move() metotları eklendi; basit kopyalama için artık shutil gerekmez. Aynı sürümde standart kütüphaneye Zstandard sıkıştırması için compression.zstd modülü geldi (PEP 784).
Python'da JSON: load, dump, loads, dumps
JSON, veri alışverişi için kullanılan metin tabanlı bir biçimdir: API'ler bu biçimde yanıt verir, yapılandırmalar ve raporlar bu biçimde saklanır. json modülü iki işlemi yapar: serileştirme (Python nesnesi → JSON metni) ve seri durumdan çıkarma (metin → nesne). Dört fonksiyon vardır ve aralarındaki karışıklık sık sorulan bir sorudur.
| Fonksiyon | Ne yapar |
|---|---|
json.dumps(obj) | Nesne → JSON metni |
json.loads(s) | JSON metni → nesne |
json.dump(obj, f) | Nesneyi açık bir dosyaya yazar |
json.load(f) | Açık bir dosyadan JSON okur |
Akılda tutmak kolay: sondaki s, string (metin) ile çalışmak demektir; yoksa dosya ile çalışılır.
Tür eşleşmeleri
| Python | JSON |
|---|---|
dict | nesne {} |
list, tuple | dizi [] |
str | metin |
int, float | sayı |
True / False | true / false |
None | null |
Demet geri okunduğunda liste olur. Kümeler, tarihler ve Decimal ise modül tarafından tanınmaz; TypeError: Object of type ... is not JSON serializable hatası alırsınız.
JSON dosyasını nasıl kaydedersiniz
import json
from pathlib import Path
rapor = {
"ay": "2026-10",
"toplam": 15230.5,
"kategoriler": {"yiyecek": 8200, "ulaşım": 2100},
"etiketler": ["ev", "iş"],
}
yol = Path("veri/rapor.json")
yol.parent.mkdir(parents=True, exist_ok=True)
with yol.open("w", encoding="utf-8") as f:
json.dump(rapor, f, ensure_ascii=False, indent=2)
ensure_ascii=False Türkçe karakterleri olduğu gibi yazar. Bu parametre olmazsa dosyada "yiyecek" yerine "y..." gibi kaçış dizileri görünür; bu geçerli bir JSON'dır ama insanın okuması zordur. indent=2 girintili biçimlendirme sağlar.
JSON dosyasını nasıl okursunuz
with open("veri/rapor.json", encoding="utf-8") as f:
veri = json.load(f)
print(veri["toplam"]) # 15230.5
print(veri["kategoriler"]["yiyecek"]) # 8200
Sonuç olağan bir sözlük ya da listedir ve onunla alışılmış araçlarla çalışılır. Dosya JSON değilse ya da yarım kalmışsa, satır ve konum bilgisiyle json.JSONDecodeError fırlatılır. Veri dışarıdan geliyorsa bu hatayı yakalamanız gerekir.
JSON metnini ayrıştırmak ve güzel yazdırmak
import json
ham = '{"ad": "Ayşe", "beceriler": ["python", "sql"], "aktif": true}'
kullanici = json.loads(ham)
print(kullanici["beceriler"][0]) # python
print(json.dumps(kullanici, ensure_ascii=False, indent=2, sort_keys=True))
sort_keys=True çıktıdaki anahtarları sıralar; böylece dosyaları git'te karşılaştırmak kolaylaşır. Terminalden bir JSON dosyasını hızlıca biçimlendirmek için yerleşik araç da vardır: python -m json.tool veri/rapor.json.
HTTP API'lerinin yanıtları da JSON metnidir. requests kütüphanesi bunu response.json() ile ayrıştırır; altta yatan işlem yine json.loads'tur.
Tuzak: JSON anahtarları her zaman metindir
d = {1: "ocak", 2: "şubat"}
geri = json.loads(json.dumps(d))
print(geri == d) # False
print(geri) # {'1': 'ocak', '2': 'şubat'}
# geri[1] -> KeyError, geri["1"] yazmalısınız
duzeltilmis = {int(k): v for k, v in geri.items()}
JSON'da nesne anahtarları yalnızca metin olabilir; bu yüzden sayısal anahtarlar serileştirme sonrasında metne dönüşür. Okurken bunları yeniden sayıya çevirin.
Kendi türleriniz: tarihler ve Decimal
import json
from datetime import date
def varsayilan(obj):
if isinstance(obj, date):
return obj.isoformat()
raise TypeError(f"{type(obj).__name__} türü serileştirilemiyor")
print(json.dumps({"gun": date(2026, 10, 1)}, default=varsayilan))
# {"gun": "2026-10-01"}
default parametresindeki fonksiyon, tanınmayan her nesne için çağrılır. Daha karmaşık durumlarda json.JSONEncoder sınıfından türetip default metodunu yeniden yazabilirsiniz.
JSON dizisine nasıl eleman eklersiniz
JSON, metin günlükleri gibi sona eklenemez: dosyayı okuyup değiştirmeniz ve tamamını yeniden yazmanız gerekir.
yol = Path("veri/kayitlar.json")
kayitlar = json.loads(yol.read_text(encoding="utf-8")) if yol.exists() else []
kayitlar.append({"id": len(kayitlar) + 1, "baslik": "yeni"})
yol.write_text(json.dumps(kayitlar, ensure_ascii=False, indent=2), encoding="utf-8")
Kayıtlar sürekli ve çok sayıda ekleniyorsa JSON Lines biçimi daha uygundur: her satırda bir JSON nesnesi bulunur ve dosya "a" modunda açılır.
Python'da CSV: csv modülü
CSV, satırların kayıt, değerlerin virgülle ayrıldığı metin tablosudur. csv modülü tırnakları, değerlerin içindeki virgülleri ve satır sonlarını doğru işler; elle yazılmış split(",") bunları yapamaz.
import csv
with open("veri/harcamalar.csv", newline="", encoding="utf-8") as f:
reader = csv.DictReader(f)
toplam = 0.0
for row in reader:
toplam += float(row["tutar"])
print(row["tarih"], row["kategori"], row["tutar"])
print("Toplam:", toplam)
csv.DictReader her satırı, dosyanın başlık satırına göre bir sözlüğe çevirir. Tüm değerler metin olarak gelir; sayıları ve tarihleri kendiniz çevirin (float, int, date.fromisoformat). Türkçe Excel'in kaydettiği, ayırıcısı noktalı virgül (;) olan dosyaları delimiter=";" parametresiyle okursunuz.
satirlar = [
{"tarih": "2026-10-01", "kategori": "yiyecek", "tutar": 450},
{"tarih": "2026-10-02", "kategori": "ulaşım", "tutar": 60},
]
with open("veri/cikti.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=["tarih", "kategori", "tutar"])
writer.writeheader()
writer.writerows(satirlar)
Yazarken newline="" zorunludur: yoksa Windows'ta satırlar arasında boş satırlar belirir. Dosya Excel'de açılacaksa encoding="utf-8-sig" kullanın; başındaki BOM işareti Excel'in UTF-8'i tanımasını sağlar.
CSV'den JSON'a: tam örnek
import csv
import json
from collections import defaultdict
from pathlib import Path
kaynak = Path("veri/harcamalar.csv")
hedef = Path("veri/rapor.json")
kategori_toplam = defaultdict(float)
with kaynak.open(newline="", encoding="utf-8") as f:
for row in csv.DictReader(f):
kategori_toplam[row["kategori"]] += float(row["tutar"])
rapor = {"toplam": sum(kategori_toplam.values()), "kategoriler": dict(kategori_toplam)}
hedef.write_text(json.dumps(rapor, ensure_ascii=False, indent=2), encoding="utf-8")
print(hedef.read_text(encoding="utf-8"))
Her rapor betiğinin çekirdeği budur: CSV'den girdi okunur, bir sözlükte toplanır ve JSON olarak çıktı verilir.
Tipik hatalar
FileNotFoundError— yol göreli ve komutun çalıştığı klasöre göre hesaplanıyor, betiğin klasörüne göre değil.Path(__file__).parentkullanın.- Dosya boşaldı —
"w"yerine"a"açılması gerekirken"w"açıldı. UnicodeDecodeError— dosya farklı bir kodlamada; kodlamayı açıkça belirtin (cp1254,utf-8-sig).TypeError: Object of type set is not JSON serializable— listeye çevirin ya dadefaultfonksiyonu verin.- JSON yüklendikten sonra
KeyError— sayısal anahtarlar metne dönüşmüş. - Kendi dosyanız
json.pyya dacsv.pyadını taşıyor — standart modülü gölgeler veimport jsonsizin dosyanızı içe aktarır.
Özet
Python'da JSON için standart kütüphane yeterlidir: dosyalar için json.load ve json.dump, metinler için loads ve dumps; okunabilir çıktı için ensure_ascii=False ve indent. Dosyaları kodlamayı belirterek with ile açın, yolları pathlib ile kurun, tabloları csv.DictReader ile okuyun. Kursta bu konu uygulamalı işlenir: harcama takipçisi CSV'den harcamaları okur ve raporu JSON olarak kaydeder.
Sık sorulan sorular
json.load ile json.loads arasındaki fark nedir?
json.load açık bir dosya nesnesinden okur, json.loads ise metni ayrıştırır. Benzer biçimde json.dump dosyaya yazar, json.dumps ise metin döndürür.
Türkçe karakterleri JSON'da \u kaçış dizileri olmadan nasıl kaydederim?
json.dump ya da json.dumps içinde ensure_ascii=False verin ve dosyayı encoding="utf-8" ile açın.
JSON ile çalışmak için kütüphane kurmam gerekir mi?
Hayır, json modülü standart kütüphanenin parçasıdır; import json yazmak yeterlidir.
JSON'a tarih ya da küme kaydedebilir miyim?
Doğrudan olmaz: tarihi isoformat ile metne, kümeyi listeye çevirin ya da default parametresine bir fonksiyon verin.
Belleğe sığmayan büyük bir JSON dosyasını nasıl okurum?
json.load dosyanın tamamını okur. Büyük veri için JSON Lines biçimini kullanın ve her satırı json.loads ile ayrı ayrı işleyin.
Bu konu “Python 3.15: от новичка до профи” kursunda uygulamalı olarak ayrıntılı işleniyor.
Kursa git