Rehber

Python'da JSON: dosya okuma ve yazma, CSV, pathlib ve UTF-8 kodlaması

Güncellendi: · Skillaria.Top

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.

ModNe 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.

FonksiyonNe 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

PythonJSON
dictnesne {}
list, tupledizi []
strmetin
int, floatsayı
True / Falsetrue / false
Nonenull

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__).parent kullanı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 da default fonksiyonu verin.
  • JSON yüklendikten sonra KeyError — sayısal anahtarlar metne dönüşmüş.
  • Kendi dosyanız json.py ya da csv.py adını taşıyor — standart modülü gölgeler ve import json sizin 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 konuyu videoyla öğrenin

Bu konu “Python 3.15: от новичка до профи” kursunda uygulamalı olarak ayrıntılı işleniyor.

Kursa git