Dosyalar ve basit CSV

Şimdiye kadar verileri doğrudan kodun içine yazdık. Program kapanınca ya da kod değişince bu değerleri saklayan ayrı bir yer yoktu. Gerçek uygulamalarda veri çoğu zaman bir dosyadan okunur, sonuç da bir dosyaya yazılır.

Bu hafta önce metin dosyası açmayı, okumayı ve yazmayı öğreneceğiz. Sonra satır ve sütunlardan oluşan basit CSV dosyalarını okuyacağız. Sayfadaki hücreler dosyaları tarayıcının içinde, bu sayfaya ait geçici bir alanda oluşturur. Bilgisayarınızdaki dosyalara dokunmaz, sayfayı yenileyince bu dosyalar silinir. Kendi bilgisayarınızda çalıştıracağınız programı bölümün sonunda ayrıca göstereceğiz.

Bu sayfadaki kod hücreleri kendiliğinden çalışmaz. Her hücrede önce çıktıyı tahmin edin, sonra Run Code düğmesine basın. Kodu değiştirip yeniden çalıştırabilir, Start Over ile ilk hâline döndürebilirsiniz.

Bu bölümün kapsamı

NoteSınavda sorulur
  • with open(...) kullanımı ve "r", "w", "a" kipleri
  • read(), readlines() ve dosya üzerinde for farkı
  • Kodlama seçeneğinin etkisi ve BOM sorunu
  • CSV’de sütun ayıracını delimiter ile belirleme
  • csv.DictReader ile okunan alanların metin gelmesi ve dönüştürülmesi
  • Ondalık virgül sorunu ve replace() çözümünün sınırı
  • Okuma, dönüştürme ve hesaplama adımlarının ayrılması
  • csv.writer ile yazma seçeneklerinin ayrıntısı
  • pathlib ile yol işlemleri
  • newline="" seçeneğinin satır sonlarını nasıl işlediği (kalıbın parçası olarak yazılır, ayrıntısı sorulmaz)
  • İkili (binary) dosya kipleri

Bu başlıklar konunun devamıdır. İleride karşınıza çıkar, ama bu derste ezberlemeniz beklenmiyor.

Kantinin satış dosyasından günün toplamını nasıl bulursunuz?

  1. bölümde kantinin fişleri programın içindeki bir listedeydi. Gerçekte kantinin kasası her satışı bir metin dosyasına satır satır yazıyor. Dosyayı Not Defteri’nde açınca şunu görüyorsunuz:
urun;adet;fiyat
Simit;2;12,5
Çay;4;10
Tost;3;45,0

Her akşam bir program bu dosyayı okuyacak, günün toplam satışını hesaplayacak ve sonucu rapor.txt dosyasına bir satır olarak yazacak. Programın adımlarını 1. bölümdeki gibi sözde kodla, Türkçe ve madde madde yazın. Sonra adımlarınızı dört durumla deneyin:

  1. Dosyanın ilk satırı urun;adet;fiyat. Adımlarınız bu satırı da bir satış gibi hesaba katıyor mu?
  2. Simit;2;12,5 satırını parçalara ayırıyorsunuz. Virgülden bölerseniz kaç parça çıkar? Siz neye göre böldünüz?
  3. Ertesi gün kasaya pasta eklendi: Pasta;1;1.250,00. Adımlarınız bu fiyatı kaç lira olarak okuyor?
  4. Program üç akşam çalıştı. rapor.txt dosyasında kaç satır olmalı? Adımlarınıza göre kaç satır var?

Python bilmeniz gerekmiyor: “Her satırda adedi fiyatla çarp” da bir adım. Adımlarınızı bir kenara yazın. Bölümde her birinin Python’da nasıl yazıldığını göreceğiz. Alıştırmalardan önce listenize döneceğiz.

with open(...) ile dosya açmak

Bir sınıfın puanları puanlar.txt dosyasında duruyor, her satırda bir puan:

70
82
91
65

Aşağıdaki hücrenin ilk üç satırı bu dosyayı oluşturur. Dosyaya yazmayı birazdan göreceğiz. Şimdilik sonraki satırlara bakın: dosyayı açıp içeriğini okuyorlar. Hücre ne yazar?

open() çağrısındaki parçalar:

  • "puanlar.txt": dosyanın yolu
  • "r": okuma kipi
  • encoding="utf-8": dosyanın kodlaması (encoding). Kodlama, dosyada saklanan byte’ların hangi harflere karşılık geldiğini söyleyen kuraldır. ğ, ş gibi harflerin doğru okunması buna bağlıdır.
  • as dosya: açılan dosyaya verdiğimiz ad

with bloğu bitince Python dosyayı kendiliğinden kapatır. Blokta bir hata çıksa bile dosya kapanır.

Important

Bu derste dosyaları with open(...) kalıbıyla açacağız.

Okuma, yazma ve ekleme kipleri

open() çağrısındaki ikinci argüman kipi (mode), yani dosyayla ne yapacağınızı belirler:

Kip Anlam
"r" Dosyayı okumak
"w" Dosyaya yazmak. Dosya varsa önce eski içeriği silinir
"a" Dosyanın sonuna eklemek (append)

Aşağıdaki hücre gunluk.txt dosyasına önce "w" ile, sonra "a" ile yazıyor, en sonda da dosyayı okuyor. Dosyada kaç satır vardır? Hücreyi ikinci kez çalıştırırsanız kaç satır olur?

Şimdi ilk with bloğunu ("w" ile yazan iki satırı) silin ve hücreyi üç kez çalıştırın. Dosyada kaç satır olur?

İlk hâlinde dosyada iki satır vardır: Kayıt başladı ve Yeni kayıt. Hücreyi kaç kez çalıştırırsanız çalıştırın sonuç değişmez, çünkü "w" her çalıştırmada eski içeriği silip baştan yazar.

İlk blok silinince dosyayı artık hiçbir satır temizlemez. "a" her çalıştırmada sona bir Yeni kayıt satırı ekler. Önceki iki satırın üstüne üç satır daha gelir ve dosyada beş satır olur.

Warning

"w" ile yanlış dosyayı açarsanız içindeki veri silinir. "a" ise program her çalıştığında yeniden ekler. Başlık satırını da her seferinde yazarsanız dosyada aynı başlık birkaç kez görünür. Kipi seçmeden önce dosyada sonunda neyin kalması gerektiğini düşünün.

Dosya yolu ve çalışma dizini

Dosya adının önüne klasör adı da yazabilirsiniz: "veriler/puanlar.txt". Böyle bir yola göreli yol denir. Python göreli yolu programın çalışma dizinine göre arar. Çalışma dizini, programın o anda içinde çalıştığı klasördür.

Çalışma klasörü, göreli yol ve with open kullanımı arasındaki ilişki.

Çalışma dizini ve göreli yol

Bu sayfada veriler adlı bir klasör yok. Hücre ne olur?

Dosya bulunamazsa Python FileNotFoundError verir. Bu hatayı aldığınızda iki soruya bakın: program hangi dizinden çalışıyor ve dosya yolu o dizine göre doğru mu?

read(), readlines() ve satır satır okuma

Bir dosyayı üç farklı biçimde okuyabiliriz.

read() → tek bir string

read() dosyanın henüz okunmamış kısmını, yeni açılmış bir dosyada bütün içeriği tek bir string olarak döndürür. Aşağıdaki döngü read() sonucunu dolaşıyor. Her turda ne yazdırılır: bir puan mı, başka bir şey mi?

type() satırı <class 'str'> yazar. Bir string üzerinde for karakter karakter dolaşır: önce 7, sonra 0, sonra satır sonu karakteri. Satır sonu karakteri yazdırılınca çıktıda boş satırlar görünür. Döngü puanları değil, karakterleri ve aralardaki boş satırları yazar.

readlines() → string listesi

readlines() her satırı ayrı bir string olarak tutan bir liste döndürür. Hücre ne yazar? Satırların sonunda ne görüyorsunuz?

Satırların sonundaki \n satır sonu karakteridir. Dosyanın son satırında bulunmayabilir.

Dosya nesnesi üzerinde for → satır satır

Dosyanın kendisi üzerinde for yazarsanız döngü her turda bir satır alır. strip() satır sonundaki \n’i atar. Aşağıdaki hücre puanların ortalamasını hesaplıyor. Ne yazar?

Satır satır çalışırken bu derste çoğunlukla for satir in dosya yazacağız. Bilmeniz gereken şu: read() tek bir string, readlines() satır listesi verir, dosya üzerinde for ise satırları tek tek dolaşır.

Alıştırma: satırlardaki sayıları toplayın

pass satırının yerine, her satırı sayıya çevirip toplama ekleyen kodu yazın. Beklenen sonuç 500’dür.

deger = int(satir.strip()) ve toplam = toplam + deger kullanabilirsiniz.

# Hazırlık: satislar.txt dosyasını oluşturur
with open("satislar.txt", "w", encoding="utf-8") as dosya:
    dosya.write("120\n145\n98\n137\n")

toplam = 0

with open("satislar.txt", "r", encoding="utf-8") as dosya:
    for satir in dosya:
        deger = int(satir.strip())
        toplam = toplam + deger

print(toplam)

CSV nedir?

CSV, bir tabloyu düz metin olarak saklamanın yaygın bir yoludur. Dosyanın her satırı tablonun bir satırıdır. Sütunların arasına bir ayraç konur. Adı İngilizce “comma-separated values” (virgülle ayrılmış değerler) sözlerinden gelir. Ama ayraç her zaman virgül olmaz, kantinin dosyasında noktalı virgüldür.

Basit örnek:

ad,puan,bolum
Deniz,78,Bilgisayar
Ayse,92,Siber
Mert,55,Bilgisayar

Bir CSV satırını split(",") ile kendiniz bölebilirsiniz. Ama içinde virgül geçen bir alan CSV’de tırnak içinde yazılır: "Ankara, Çankaya". Aşağıdaki satır kaç parçaya bölünür?

split() tırnağı tanımaz ve adresi ikiye böler. Bu yüzden CSV okurken Python’ın standart kütüphanesindeki csv modülünü kullanacağız.

csv.reader ve newline=""

csv.reader her satırı alanlarına ayırır. Hücre her satır için ne yazar? Tırnak içindeki adres kaç alan olur?

newline="" yazınca satır sonlarını csv modülü kendi kurallarıyla işler. Python belgeleri bu kalıbı önerir: böylece Windows’ta da öteki işletim sistemlerinde de CSV okurken ya da yazarken fazladan boş satır ve satır sonu karışıklığı çıkmaz.

Note

newline="" sütunları ayırmaz. Sütunlar arasındaki virgülü ya da noktalı virgülü, yani sütun ayıracını delimiter belirler. newline yalnızca satır sonlarıyla ilgilidir.

CSV açarken newline="" yazmayı alışkanlık hâline getirin. Nasıl çalıştığı sınavda sorulmaz.

csv.DictReader

DictReader her satırı bir sözlük olarak verir. Sözlüğün anahtarları dosyanın ilk satırındaki sütun adlarıdır. Hücrenin son satırı hangi türü yazar?

İlk satır (ad,puan,bolum) bir kayıt olarak gelmez, sütun adı olur. Değerlerin hepsi string olarak gelir: "78" bir sayı değil, metindir. Hesap yapmadan önce dönüştürmeniz gerekir:

puan = int(kayit["puan"])

CSV satırının DictReader ile okunup tür dönüşümleri yapılmış Python kaydına dönüştürülmesi.

CSV satırından Python kaydına

Türkiye’de Excel’den gelen CSV: ;, BOM ve ondalık virgül

Bilgisayarın bölge ayarı Türkiye olduğunda Excel ve benzeri tablo programlarının kaydettiği CSV dosyaları çoğu zaman kantinin dosyasına benzer:

urun;adet;fiyat
Simit;2;12,5
Çay;4;10
Tost;3;45,0

Bu dosyada üç ayrı sorun var.

1. Sütun ayıracı noktalı virgül olabilir

csv.DictReader(dosya) varsayılan olarak virgül bekler. Aşağıdaki hücre kantinin dosyasını ayraç vermeden okuyor. Her kayıtta kaç anahtar var?

Okuyucu satırlarda virgül aradı. Noktalı virgülü ayraç saymadığı için bütün başlık tek bir sütun adı oldu: 'urun;adet;fiyat'. Her kayıtta bu anahtarın altında satırın tamamı duruyor. 12,5 içindeki virgülü ise ayraç sandı ve fiyatı ikiye böldü: virgülden sonraki 5, adı olmayan fazladan bir alan olarak None anahtarının altına düştü.

Ayıracı açıkça verin. Hücredeki csv.DictReader(dosya) çağrısını aşağıdaki gibi değiştirip yeniden çalıştırın:

okuyucu = csv.DictReader(dosya, delimiter=";")

2. Dosyanın başında UTF-8 BOM olabilir

Bazı programlar UTF-8 kodlamalı bir CSV dosyasının en başına BOM (byte order mark) adlı görünmez bir işaret koyar. Dosya Not Defteri’nde açılınca bu işaret görünmez. Dosyayı encoding="utf-8" ile açarsanız işaret ilk sütun adına yapışır.

Aşağıdaki hücrede dosyayı Excel gibi BOM ekleyerek kaydediyoruz, sonra utf-8 ile okuyoruz. İlk print() ne yazar? İkinci print() çalışır mı?

İlk satır sütun adlarını yazar. İlk ad 'urun' değil, 'urun' olarak görünür: başındaki  BOM işaretidir. Sözlükte "urun" adlı bir anahtar olmadığı için ikinci print() KeyError verir. Not Defteri’nde dosya kusursuz görünür ama Python’ın gördüğü ad başkadır.

Böyle dosyaları utf-8-sig kodlamasıyla açın. Hücrede okuma satırındaki encoding="utf-8" değerini encoding="utf-8-sig" yapıp yeniden çalıştırın:

with open("satislar.csv", "r", encoding="utf-8-sig", newline="") as dosya:
    okuyucu = csv.DictReader(dosya, delimiter=";")

utf-8-sig, dosyanın başında BOM varsa okurken onu atar. BOM olmayan bir UTF-8 dosyayı da okuyabilir. Yine de dosyanın hangi kodlamayla kaydedildiğini bilmek her zaman daha iyidir.

3. Ondalık ayracı virgül olabilir

float() ondalık ayracı olarak nokta bekler. Aşağıdaki üç satırdan hangisi hata verir?

Verinin biçimini biliyorsanız ve virgül yalnızca ondalık ayracı olarak kullanılıyorsa virgülü noktaya çevirip dönüştürebilirsiniz:

fiyat_metni = kayit["fiyat"]
fiyat = float(fiyat_metni.replace(",", "."))

Üç çözüm bir arada. Hücre her satır için ne yazar? fiyat hangi türde?

Warning

replace(",", ".") yalnızca sayıların ondalık virgülle ve binlik ayracı olmadan yazıldığını bildiğiniz basit örneklerde güvenlidir. Pastanın fiyatı 1.250,00 ise replace() sonucu 1.250.00 olur ve float() hata verir. Binlik ayracının virgül olduğu bir biçimde 1,250 ise hata vermeden 1.25 olur. Böyle veride önce sayıların nasıl yazılacağı açıkça kararlaştırılmalı ya da bölgesel biçimleri tanıyan bir araç kullanılmalıdır.

Important

Bir CSV dosyasının biçimini uzantısına bakıp tahmin etmeyin. Ayracı, kodlamayı ve sayıların nasıl yazıldığını dosyayı açıp öğrenin. Excel’den aldığınız dosyada ;, BOM ya da 12,5 görmeniz Python’ın bozulduğunu göstermez. Bunlar veriyle çalışırken sık karşılaşılan durumlardır.

Alıştırma: geçen öğrencileri sayın

Puanı 60 ve üzeri olan öğrencileri sayın. Beklenen sonuç 3’tür.

puan = int(kayit["puan"]) ile başlayın.

import csv

# Hazırlık: notlar.csv dosyasını oluşturur
with open("notlar.csv", "w", encoding="utf-8") as dosya:
    dosya.write("""ad,puan
Deniz,78
Ayse,92
Mert,55
Ece,60
""")

gecen_sayisi = 0

with open("notlar.csv", "r", encoding="utf-8", newline="") as dosya:
    okuyucu = csv.DictReader(dosya)

    for kayit in okuyucu:
        puan = int(kayit["puan"])
        if puan >= 60:
            gecen_sayisi = gecen_sayisi + 1

print(gecen_sayisi)

CSV’den sözlük listesi oluşturmak

Okunan her satırdan yeni bir sözlük oluşturup puan alanını sayıya çeviriyoruz. Ortaya bir sözlük listesi (her elemanı bir öğrencinin kaydı olan liste) çıkar. Hücre ilk kaydı yazdırıyor. puan tırnaklı mı görünür, tırnaksız mı?

Elimizde artık 11. bölümdeki gibi bir sözlük listesi var. Orada yazdığımız fonksiyonları bu listeyle de kullanabiliriz. Akış şöyle:

dosyadan okuma
    ↓
türleri dönüştürme
    ↓
program içi veri yapısı
    ↓
hesaplama, filtreleme, raporlama

Her adım ayrı denenebilir. Bozuk bir CSV alanı ile yanlış bir ortalama formülü farklı sorunlardır. Adımlar ayrı olunca hangisinde hata olduğunu bulmak kolaylaşır.

Dosyaya yazmak ve eklemek

Kantinin programı her akşam günün toplamını rapor.txt dosyasına yazacak. Aşağıdaki hücre üç akşamı bir döngüyle taklit ediyor: önce rapora bir başlık yazıyor, sonra her akşamın toplamını yazıyor. Döngüden sonra dosyada hangi satırlar kalır?

Döngüdeki "w"’yi "a" yapıp yeniden çalıştırın. Bu kez kaç satır kalır?

Döngüdeki "w" her turda dosyayı baştan yazar. Önce başlık, sonra ilk iki akşamın satırı silinir ve yalnız Günün toplamı: 240.00 TL kalır.

"a" ile her akşamın satırı sona eklenir ve dosyada dört satır olur: başlık ve üç akşam. Hücreyi yeniden çalıştırınca da dört satır kalır, çünkü ilk blok başlığı "w" ile yazarak dosyayı her seferinde temizler.

csv.DictWriter gibi CSV yazma araçları sınavda sorulmaz. Bu hafta okuma, dönüştürme ve rapor yazma akışını anlamanız yeterli.

Dosyayla çalışırken çıkan hatalar

Dosyayla çalışırken kodunuz söz dizimi açısından doğru olsa bile hata alabilirsiniz:

  • Dosya bulunamıyor: FileNotFoundError
  • Beklenen sütun yok: kayit["puan"] gibi erişimlerde KeyError. BOM yüzünden ilk sütunun adı değişmişse de bu hata çıkar.
  • "puan" alanı sayı değil: ValueError
  • Dosya boş: döngü hiç çalışmaz. Ortalama hesaplanırken adet 0 kaldığı için ZeroDivisionError (sıfıra bölme hatası) çıkar.
  • Karakter kodlaması beklenenden farklı: UnicodeDecodeError ya da bozuk görünen harfler
  • delimiter yanlış: beklenen sütunlar hiç oluşmaz

13. bölümde bu hatalara döneceğiz: FileNotFoundError, KeyError, ValueError gibi istisnaları (program çalışırken çıkan ve programı durduran hataları) try/except ile yakalamayı ve hata mesajını okumayı öğreneceğiz.

Soruya dönelim: kantinin satış dosyası Python’da

Bölümün başında kantinin programı için adımlar yazıp dört durumla denemiştiniz. Python’daki karşılıkları şöyle:

Adım ya da durum Sözde kodda Python’da Dikkat
Dosyayı açmak “Satış dosyasını aç” with open("satislar.csv", "r", encoding="utf-8-sig", newline="") as dosya: Kodlama verilmezse Çay’daki Ç bozulabilir. Excel’in eklediği BOM için utf-8-sig
İlk satır urun;adet;fiyat “İlk satırı atla” csv.DictReader(dosya, delimiter=";") DictReader ilk satırı sütun adı yapar, satış olarak saymaz
Simit;2;12,5 satırını bölmek “Noktalı virgülden böl” delimiter=";" Varsayılan ayraç virgüldür. Virgülden bölünürse 12,5 iki alana ayrılır
Adedi fiyatla çarpmak “Adedi fiyatla çarp” int(kayit["adet"]) * float(kayit["fiyat"].replace(",", ".")) Alanlar metin gelir. Dönüştürmeden çarpılırsa TypeError çıkar
Pasta;1;1.250,00 “Virgülü noktaya çevir” replace(",", ".") bu satırda yetmez 1.250.00 olur ve float() hata verir. Sayıların biçimi önceden kararlaştırılır
Üç akşamın raporu “Toplamı rapora yaz” with open("rapor.txt", "a", encoding="utf-8") as dosya: "w" her akşam eski satırı siler. Üç akşamdan sonra tek satır kalır

Listenizi tabloyla karşılaştırın. “Her satırı virgülden ayır” yazdıysanız kantinin dosyasında fiyatlar ikiye bölünür. “Rapora yaz” yazıp nasıl yazılacağını söylemediyseniz Python’da bu, "w" ile "a" arasında bir seçimdir. Adımlarınızı “oku, çevir, hesapla, yaz” diye ayırdıysanız programı da aynı parçalara bölebilirsiniz.

Üret: kantinin günlük toplamı

Kantinin dosyasını okuyup günün toplam satışını döndüren gunun_toplami() fonksiyonunu yazın. Fonksiyon dosya adını alır, dosyayı utf-8-sig ve newline="" ile açar, DictReader’a ayracı verir, her satırda adedi tam sayıya, fiyatı ondalık sayıya çevirir ve adet * fiyat değerlerinin toplamını döndürür. Bu dosya için beklenen sonuç 200.0.

Fonksiyonun içinde önce toplam = 0 yazın. with open(dosya_adi, "r", encoding="utf-8-sig", newline="") as dosya: bloğunda csv.DictReader(dosya, delimiter=";") ile satırları dolaşın. Döngüden sonra return toplam.

import csv

# Hazırlık: satislar.csv dosyasını BOM ekleyerek oluşturur
with open("satislar.csv", "w", encoding="utf-8-sig") as dosya:
    dosya.write("""urun;adet;fiyat
Simit;2;12,5
Çay;4;10
Tost;3;45,0
""")

def gunun_toplami(dosya_adi):
    toplam = 0

    with open(dosya_adi, "r", encoding="utf-8-sig", newline="") as dosya:
        okuyucu = csv.DictReader(dosya, delimiter=";")

        for kayit in okuyucu:
            adet = int(kayit["adet"])
            fiyat = float(kayit["fiyat"].replace(",", "."))
            toplam = toplam + adet * fiyat

    return toplam

print(gunun_toplami("satislar.csv"))

Kendi bilgisayarınızda deneyin

Aynı programı bu kez gerçek dosyalarla çalıştırın.

  1. VS Code’da bir klasör açın. Not Defteri’nde bölümün başındaki kantin dosyasını yazıp bu klasöre satislar.csv adıyla kaydedin.
  2. Aynı klasöre kantin.py adlı bir dosya oluşturun. Üret alıştırmasındaki gunun_toplami() fonksiyonunu (hazırlık satırları olmadan) içine yazın ve altına şu satırları ekleyin:
toplam = gunun_toplami("satislar.csv")

with open("rapor.txt", "a", encoding="utf-8") as dosya:
    dosya.write(f"Günün toplamı: {toplam:.2f} TL\n")

print("Rapora eklendi:", toplam)
  1. Programı üç kez çalıştırın ve rapor.txt dosyasını Not Defteri’nde açın. Üç satır görmelisiniz.

Sonra Excel’de ya da başka bir tablo programında küçük bir tablo hazırlayıp CSV olarak kaydedin. Dosyayı Not Defteri gibi bir metin düzenleyicide açın ve şu üç soruyu cevaplayın:

  1. Sütun ayıracı , mı, ; mi?
  2. Ondalık sayılar 12.5 mi, 12,5 mi?
  3. Python’da utf-8 ile okuyunca ilk sütun adı tuhaf görünüyorsa utf-8-sig ile düzeliyor mu?

Bu incelemede CSV’nin bir Excel dosyası değil, düz metin olduğunu göreceksiniz. Bir CSV’yi doğru okumak için ayracını, kodlamasını ve sayıların nasıl yazıldığını bilmeniz gerekir.

Sınav provası

Önce kendi cevabınızı seçin, sonra cevap anahtarında her şıkkın neden doğru ya da yanlış olduğunu okuyun. Yanlış şıklar rastgele yazılmadı; bu konuda öğrencilerin gerçekten yaptığı hatalardan seçildi. Sınav soruları da aynı yolla hazırlanır.

Madde 1. "r", "w" ve "a" kipleri arasındaki fark nedir?

  • A. "r" okur, "w" baştan yazar, "a" sona ekler
  • B. Üçü de okuma kipidir; fark yalnızca hızdadır
  • C. "r" okur; "w" ve "a" dosya yoksa hata verir
  • D. "r" okur, "w" sona ekler, "a" içeriği siler
  • E. "r" ve "w" metin, "a" ikili dosyalar içindir

Madde 2. with open(...) yapısı ne kazandırır?

  • A. Kodlama sorunlarını kendiliğinden çözer
  • B. Dosyayı salt okunur açar; yanlışlıkla yazmayı önler
  • C. Dosyayı tek seferde belleğe alıp daha hızlı okur
  • D. Dosyanın var olduğunu garanti eder
  • E. Blok bitince, hata çıksa bile dosyayı kapatır

Madde 3. read() ile readlines() hangi türde değer döndürür?

  • A. read() liste, readlines() tek metin döndürür
  • B. İkisi de satırlardan oluşan bir liste döndürür
  • C. read() tek bir metin, readlines() satır listesi döndürür
  • D. read() sayı, readlines() metin döndürür
  • E. İkisi de dosyanın tamamını tek metin olarak döndürür

Madde 4. CSV okunduğunda ilk sütun adı ad görünüyor. Hangi seçenek yardımcı olur?

  • A. newline="" eklemek
  • B. Dosyayı encoding="utf-8-sig" ile açmak
  • C. delimiter=";" vermek
  • D. Dosyayı ikili kipte açmak
  • E. Sütun adını strip() ile kırpmak yeterlidir

Madde 5. Türkçe bölgesel ayarlı bir tablo uygulamasından gelen ad;puan satırı tek sütun gibi okunuyor. Hangi ayar kontrol edilmelidir?

  • A. newline=""
  • B. encoding="utf-8-sig"
  • C. Dosyayı "a" kipinde açmak
  • D. delimiter=";" vermek
  • E. Satırı split(" ") ile bölmek

Madde 6. csv.DictReader ile okunan bir satırda "78" değeri neden doğrudan sayısal puan olarak kullanılmamalıdır?

  • A. 78 geçersiz bir puan olduğu için
  • B. DictReader yalnızca başlık satırını okuduğu için
  • C. Kullanılabilir; DictReader sayıları kendiliğinden dönüştürür
  • D. Tırnak işaretleri değerin parçası olduğu için
  • E. CSV’den gelen bütün alanlar metin olarak okunur

Madde 7. float("12,5") neden hata verir?

  • A. Virgül Python’da ayrılmış bir karakterdir
  • B. 12,5 çok büyük bir sayı olduğu için
  • C. float() yalnızca tam sayı kabul eder
  • D. float() ondalık ayracı olarak nokta bekler
  • E. Değer tırnak içinde olduğu için

Madde 8. replace(",", ".") neden her yerel sayı biçimi için güvenli bir genel çözüm değildir?

  • A. replace() yalnızca ilk eşleşmeyi değiştirir
  • B. replace() metinlerde çalışmaz
  • C. Bazı biçimlerde virgül binlik ayracıdır
  • D. Sonuç str kaldığı için dönüşüm eksik kalır
  • E. Güvenlidir; virgül her zaman ondalık ayracıdır

Madde 9. Dosya okuma, tür dönüştürme ve hesaplama adımlarını ayrı fonksiyonlara bölmenin yararı nedir?

  • A. Hatanın hangi adımda olduğu kolayca bulunur
  • B. CSV ayracı kendiliğinden bulunur
  • C. Tür dönüşümü gereksiz hâle gelir
  • D. Dosya kapatma işlemi gereksiz hâle gelir
  • E. Dosya okuma işlemi hızlanır

Madde 1. Doğru: A. "w" ile açılan dosyanın eski içeriği silinir ve dosya baştan yazılır. Var olan veriyi korumak istiyorsanız "a" kullanılır; yeni içerik dosyanın sonuna eklenir.

  • B yanlış: Üçü de open() çağrısında aynı yere yazıldığı için benzer işler sanılabilir. Ama yalnızca "r" okuma kipidir.
  • C yanlış: "r" dosya yoksa gerçekten hata verir, bu yüzden öteki kiplerin de öyle davranacağı sanılır. Ama "w" ve "a" dosya yoksa oluşturur.
  • D yanlış: Kip harflerinin anlamı akılda kalmazsa "w" ile "a" kolayca yer değiştirir. Ama "w" baştan yazar, "a" (“append”, eklemek) sona ekler; hiçbir kip içeriği yalnızca silmek için açılmaz.
  • E yanlış: Kip harflerinin bir kısmı ikili dosyalarla ilgili olduğu için karışabilir. Ama ikili kip için "b" eklenir; "a" da metin kipidir.

Madde 2. Doğru: E. close() çağrısını elle yazmayı unutabilir ya da araya giren bir hata yüzünden o satıra hiç gelemeyebilirsiniz. with blok bittiğinde dosyayı kendiliğinden kapatır; bu sorun olmaz.

  • A yanlış: with ile encoding çoğu zaman aynı satırda göründüğü için karışabilir. Ama kodlama encoding ile ayrıca belirtilir.
  • B yanlış: Örneklerin çoğu okuma için açıldığı için böyle sanılabilir. Ama kip, open() çağrısındaki argümanla belirlenir; with kipi değiştirmez.
  • C yanlış: Önerilen yazım olduğu için bir hız kazancı getirdiği düşünülebilir. Ama with okuma hızını değiştirmez; dosyayı nasıl okuyacağınız ayrı bir karardır.
  • D yanlış: Güvenli yazım olarak anlatıldığı için her sorunu önlediği sanılabilir. Ama dosya yoksa yine FileNotFoundError çıkar.

Madde 3. Doğru: C. read() dosyanın tamamını tek bir metin olarak verir. readlines() ise her satırı bir eleman olan bir liste döndürür. Satır satır işlemek istiyorsanız readlines() ya da doğrudan dosya üzerinde for kullanılır.

  • A yanlış: İki ad birbirine benzediği için türler kolayca karışır. Ama iki tür ters yazılmış; çoğul ad readlines() listeyi verir.
  • B yanlış: Dosya satırlardan oluştuğu için her okumanın satır listesi vereceği sanılabilir. Ama read() tek bir string döndürür.
  • D yanlış: Dosyada sayılar yazılıysa read() sonucunun sayı olacağı düşünülebilir. Ama dosyadan okunan içerik her zaman metindir.
  • E yanlış: İkisi de dosyanın bütün içeriğini okuduğu için akla yatkın gelir. Ama readlines() bu içeriği satırlara bölüp liste döndürür.

Madde 4. Doğru: B. Dosyanın başındaki BOM işareti bu kodlamayla okunurken atılır; sütun adı ad olarak gelir.

  • A yanlış: CSV açarken her zaman yazılan bir seçenek olduğu için her sorunun çözümü gibi görünür. Ama bu seçenek satır sonlarıyla ilgilidir; BOM’u etkilemez.
  • C yanlış: Excel’den gelen dosyalarda BOM ile noktalı virgül çoğu zaman birlikte görüldüğü için iki çözüm karışabilir. Ama delimiter sütunları ayırır; baştaki görünmez işareti kaldırmaz.
  • D yanlış: İşaret byte düzeyinde bir sorun olduğu için ikili kip akla gelebilir. Ama ikili kipte içerik metne hiç çevrilmez, byte olarak gelir; DictReader bununla çalışmaz ve sorun çözülmez.
  • E yanlış: İşaret görünmediği için baştaki bir boşluk sanılabilir ve strip() akla gelir. Ama strip() boşluk karakterlerini kırpar; BOM bir boşluk karakteri değildir ve adda kalır.

Madde 5. Doğru: D. Bu dosyada sütun ayracı virgül değil noktalı virgüldür. CSV okuyucusu varsayılan olarak virgül bekler. Ayraç farklıysa açıkça belirtilmelidir.

  • A yanlış: CSV okurken önerilen bir seçenek olduğu için akla yatkın gelir. Ama satır sonlarıyla ilgilidir; sütunları ayırmaz.
  • B yanlış: Tablo uygulamasından gelen dosyalarda sık gereken bir seçenek olduğu için akla gelir. Ama bu, baştaki BOM işaretini atar; sütun ayrımıyla ilgisi yoktur.
  • C yanlış: Kip değiştirmenin okumayı düzelteceği düşünülebilir. Ama kip, okunan satırın nasıl bölüneceğini değiştirmez; "a" zaten yazma kipidir.
  • E yanlış: Satırı elle bölmek hızlı bir çözüm gibi görünür. Ama boşluktan bölmek noktalı virgülü ayırmaz. Ayrıca elle bölmek tırnak içindeki ayraçları yanlış işler; csv modülü bunun için vardır.

Madde 6. Doğru: E. Sayısal işlem için alanın açıkça dönüştürülmesi gerekir. "78" + 1 hata verir; "78" > "9" ise False döner, çünkü metinler karakter karakter karşılaştırılır. Bu yüzden dönüşüm bilerek ve açıkça yapılır.

  • A yanlış: Soru bir sorun olduğunu söylediği için değerin kendisinden şüphelenilebilir. Ama değer geçerli bir puandır; sorun türündedir.
  • B yanlış: DictReader başlık satırını özel işlediği için böyle sanılabilir. Ama bütün satırları okur; başlığı anahtar olarak kullanır.
  • C yanlış: Tablo uygulamaları sayıları kendiliğinden tanıdığı için Python’ın da öyle yapacağı düşünülebilir. Ama DictReader böyle bir dönüşüm yapmaz.
  • D yanlış: Ekranda "78" tırnaklı göründüğü için akla yatkın gelir. Ama tırnaklar Python’daki gösterime aittir; değerin içinde değildir.

Madde 7. Doğru: D. float() virgüllü yazımı sayı olarak tanımaz. Verinin biçimi biliniyorsa replace(",", ".") ile düzeltilebilir; ama bu genel bir çözüm değildir.

  • A yanlış: Virgül kodda argümanları ayırdığı için özel sanılabilir. Ama metin içinde özel bir anlamı yoktur.
  • B yanlış: Virgül bazı yazımlarda binlik ayracı olduğu için sayı büyük görünebilir. Ama hatanın büyüklükle ilgisi yoktur.
  • C yanlış: int() ile karıştırıldığında akla yatkın gelir. Ama float() ondalıklı sayı içindir; float("12.5") sorunsuz çalışır.
  • E yanlış: Tırnaklı değerin sayı olmadığı doğrudur, bu yüzden sorun gibi görünür. Ama float() zaten metin alır; sorun metnin biçimindedir.

Madde 8. Doğru: C. Bin iki yüz elli anlamındaki 1,250 noktaya çevrilirse 1.25 olur. replace() virgülün ondalık ayracı mı binlik ayracı mı olduğunu bilmez. Bu yüzden yalnızca verinin biçimi biliniyorsa kullanılır.

  • A yanlış: Bazı araçlarda arama ilk eşleşmede durduğu için akla yatkın gelir. Ama replace() varsayılan davranışta bütün eşleşmeleri değiştirir.
  • B yanlış: Sorunun yöntemin kendisinde olduğu düşünülebilir. Ama replace() metinlerde çalışır; sorun, değiştirdiği virgülün ne anlama geldiğini bilmemesidir.
  • D yanlış: Sonuç gerçekten metindir, bu yüzden eksik bir adım var gibi görünür. Ama zaten sonrasında float() uygulanır.
  • E yanlış: Türkçede virgül ondalık ayracı olduğu için akla yatkın gelir. Ama birçok yerel biçimde virgül binlik ayracıdır.

Madde 9. Doğru: A. Her adım ayrı ayrı denenebilir. Bozuk bir CSV alanı ile yanlış bir ortalama formülü çok farklı sorunlardır; adımlar ayrı olunca bu iki sorun birbirine karışmaz.

  • B yanlış: Okumanın ayrı bir fonksiyona taşınması onu akıllı yapıyormuş gibi görünür. Ama ayraç yine açıkça verilir.
  • C yanlış: Dönüşüm ayrı bir fonksiyona gittiği için ortadan kalkmış gibi görünür. Ama dönüşüm yine yapılır; yalnızca kendi fonksiyonuna taşınır.
  • D yanlış: Okuma fonksiyonu bitince dosyanın kendiliğinden kapanacağı sanılabilir. Ama dosyayı with kapatır; bunun adımları bölmekle ilgisi yoktur.
  • E yanlış: Düzenli kodun daha hızlı çalışacağı düşünülebilir. Ama okuma hızı değişmez.

Tek sayfa özet

  • with open(...) dosyayı açar ve blok bitince, hata çıksa bile kendiliğinden kapatır.
  • "r" okur, "w" eski içeriği silip baştan yazar, "a" dosyanın sonuna ekler. Her akşam büyüyen bir rapor "a" ister.
  • Göreli yol çalışma dizinine göre aranır. Dosya orada yoksa FileNotFoundError çıkar.
  • read() tek bir string, readlines() string listesi döndürür. Doğrudan dosya üzerinde for satır satır dolaşır.
  • encoding="utf-8" Türkçe harflerin doğru okunmasını sağlar. Başında BOM olan UTF-8 CSV için utf-8-sig gerekir, yoksa ilk sütunun adı değişir.
  • CSV dosyasını newline="" ile açmak kalıbın parçasıdır. Satır sonlarını böylece csv modülü işler.
  • CSV sütun ayıracı her zaman virgül olmaz. Türkçe bölgesel ayarlı tablo programlarından gelen dosyalarda delimiter=";" gerekir.
  • csv.DictReader ilk satırı sütun adı yapar. Bütün alanlar string olarak gelir ve hesaptan önce dönüştürülür.
  • 12,5 gibi basit bir değeri replace() ile 12.5 yapabilirsiniz. 1.250,00 gibi binlik ayracı olan sayılarda bu yöntem işe yaramaz.
  • Okuma, tür dönüştürme ve hesaplamayı ayrı adımlarda yaparsanız kodu okumak ve hatayı bulmak kolaylaşır.

Bir sonraki bölümde istisnaları, modülleri ve adım adım hata ayıklamayı göreceğiz. Bu bölümdeki dosya ve dönüşüm hatalarını orada yakalamayı öğreneceğiz.

Bu bölümün kazanımları

Bu bölümü bitiren öğrenci:

  • with open(...) ile dosya açar ve "r", "w", "a" kiplerini ayırt eder.
  • read(), readlines() ve dosya üzerinde for davranışlarını ayırt eder.
  • Kodlama seçeneğinin metnin okunuşunu nasıl etkilediğini açıklar ve BOM sorununu tanır.
  • CSV’de sütun ayıracını delimiter ile belirler.
  • csv.DictReader ile okunan alanların metin geldiğini açıklar ve onları dönüştürür.
  • Ondalık virgüllü sayıyı dönüştürür ve replace() çözümünün sınırını açıklar.
  • Okuma, dönüştürme ve hesaplama adımlarını birbirinden ayırır.
Back to top