Dosyalar ve basit CSV

Şimdiye kadar verileri doğrudan kodun içine yazdık. Bu değerler yalnızca kodda duruyordu; program kapanınca ya da kod değişince onları 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 çalıştırılabilir örneklerde bilgisayarınızdaki dosyalara dokunmayacağız; dosya yerine bellekte duran bir metni dosya gibi okuyacağız. Kendi bilgisayarınızda çalıştıracağınız gerçek dosya kodunu da ayrıca göstereceğiz.

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; ileride karşınıza çıkar ama bu derste ezberlemeniz beklenmiyor.

Excel’den gelen CSV neden tek sütun görünüyor?

Excel’de hazırladığınız bir tabloyu CSV olarak kaydedip Python’la okudunuz ve her satır tek bir sütun olarak geldi. Böyle dosyalarda üç sorun sık görülür: sütunlar virgülle değil noktalı virgülle ayrılmış olabilir, dosyanın başında görünmeyen bir işaret bulunabilir, ondalık sayılar 12,5 gibi virgülle yazılmış olabilir. Üçü ayrı sorunlardır ve ayrı ayrı çözülür.

Dosya neden gerekir?

Bir programın şu verilerle çalıştığını düşünelim:

puanlar = [70, 82, 91, 65]

Bu liste kodun içinde yazılı. Oysa puanlar başka bir programdan gelmiş ya da bir kullanıcı onları daha önce kaydetmiş olabilir. O zaman veri bir dosyada durur.

puanlar.txt:

70
82
91
65

Program bu dosyayı okuyup veriyi işleyebilir.

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

with open("puanlar.txt", "r", encoding="utf-8") as dosya:
    icerik = dosya.read()

print(icerik)

Burada:

  • "puanlar.txt" dosya yoludur,
  • "r" okuma kipidir,
  • encoding="utf-8" dosyanın kodlamasını (encoding) belirtir. 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 dosya nesnesine verdiğimiz addır.

with bloğu bitince Python dosyayı kendiliğinden kapatı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) belirler, yani dosyayla ne yapacağınızı:

Kip Anlam
"r" Dosyayı okumak
"w" Dosyaya yazmak; dosya varsa önce eski içeriği silinir
"a" Dosyanın sonuna ekleme yapmak (append)

"w" örneği:

with open("sonuc.txt", "w", encoding="utf-8") as dosya:
    dosya.write("İşlem tamamlandı\n")

"a" örneği:

with open("gunluk.txt", "a", encoding="utf-8") as dosya:
    dosya.write("Yeni kayıt\n")

"a" var olan içeriği silmez, yeni satırı sona ekler. Bir günlüğe ya da rapora satır eklerken işe yarar.

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:

open("veriler/puanlar.txt", "r", encoding="utf-8")

Python bu yolu programın çalışma dizinine göre arar. Çalışma dizini, programın o anda içinde çalıştığı klasördür. Dosya orada bulunamazsa FileNotFoundError alırsınız.

Bu hatayı aldığınızda iki soruya bakın:

Program hangi dizinden çalışıyor?
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

with open("puanlar.txt", "r", encoding="utf-8") as dosya:
    icerik = dosya.read()

print(type(icerik))  # str

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.

Bu yüzden şu döngü

with open("puanlar.txt", "r", encoding="utf-8") as dosya:
    for deger in dosya.read():
        print(deger)

satırlar üzerinde değil, karakterler üzerinde dolaşır.

readlines() → string listesi

with open("puanlar.txt", "r", encoding="utf-8") as dosya:
    satirlar = dosya.readlines()

print(type(satirlar))  # list

Listenin her elemanı bir satırı tutan string’dir. Satırların sonunda \n (satır sonu karakteri) bulunur; dosyanın son satırında olmayabilir.

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

with open("puanlar.txt", "r", encoding="utf-8") as dosya:
    for satir in dosya:
        print(satir.strip())

Satır satır çalışırken bu derste çoğunlukla for satir in dosya yazacağız. Büyük dosyalarda hangisinin daha hızlı olduğuna girmeyeceğiz. Bilmeniz gereken şu: hangi yazım karakterleri, hangisi tek bir string’i, hangisi satır listesini verir.

Tarayıcıda dosyayı taklit etmek

StringIO, bellekteki bir metni dosya gibi okunabilen bir nesneye çevirir. Üzerinde for ile satır satır dolaşabilirsiniz. Kendi bilgisayarınızda gerçek bir dosyayla çalışırken bunun yerine with open(...) yazarsınız.

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

Her satırı sayıya çevirip toplama ekleyin. Beklenen sonuç 500’dür.

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

from io import StringIO

veri = """120
145
98
137
"""

dosya = StringIO(veri)
toplam = 0

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ı “comma-separated values” (virgülle ayrılmış değerler) ifadesinden gelir; ama ayraç her zaman virgül değildir.

Basit örnek:

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

Bir CSV satırını split(",") ile kendiniz bölerseniz içinde virgül geçen alanlarda yanlış sonuç alabilirsiniz. Böyle bir alan CSV’de "Ankara, Çankaya" gibi tırnak içinde yazılır ve split() tırnağı tanımaz. Bu yüzden Python’ın standart kütüphanesindeki csv modülünü kullanacağız.

csv.reader ve newline=""

import csv

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

    for satir in okuyucu:
        print(satir)

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

import csv

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

    for kayit in okuyucu:
        print(kayit["ad"], kayit["puan"])

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 (ad, puan, bolum). 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

Kendi hazırladığınız CSV dosyasında ayraç, ders örneklerindeki gibi , olmayabilir. Türkçe bölgesel ayarlarla çalışan Excel ve benzeri tablo programlarının (bilgisayarın bölge ayarı Türkiye olduğunda) kaydettiği dosyalar çoğu zaman şöyle görünür:

urun;adet;fiyat
Kalem;2;12,5
Defter;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. Bu yüzden noktalı virgüllü bir satırı tek bir sütun gibi okuyabilir. Ayıracı açıkça verin:

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. Dosyayı encoding="utf-8" ile açarsanız bu işaret ilk sütun adına yapışır: "ad" yerine "\ufeffad" gelir.

Böyle dosyaları utf-8-sig kodlamasıyla açın:

with open("veri.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 ayıracı virgül olabilir

float("12,5")

ValueError verir, çünkü float() ondalık ayracı olarak nokta bekler. 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:

import csv

with open("satislar.csv", "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(",", "."))
        print(kayit["urun"], adet, fiyat)
Warning

replace(",", ".") yalnızca sayıların ondalık virgülle ve binlik ayracı olmadan yazıldığını bildiğiniz basit örneklerde güvenlidir. 1.234,56, 1 234,56 ya da başka bölgesel sayı biçimlerinde bu yöntem işe yaramaz. 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 sorunlardır.

Tarayıcıda CSV okuma

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
from io import StringIO

veri = """ad,puan
Deniz,78
Ayse,92
Mert,55
Ece,60
"""

dosya = StringIO(veri)
okuyucu = csv.DictReader(dosya)
gecen_sayisi = 0

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:

import csv

ogrenciler = []

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

    for kayit in okuyucu:
        ogrenci = {
            "ad": kayit["ad"],
            "puan": int(kayit["puan"]),
            "bolum": kayit["bolum"]
        }
        ogrenciler.append(ogrenci)

Artık elimizde 11. haftadaki 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

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

Dosya okuma akışı

Dosyaya yazmak ve eklemek

Yeni bir rapor dosyası yazmak:

toplam = 450

with open("rapor.txt", "w", encoding="utf-8") as dosya:
    dosya.write(f"Toplam satış: {toplam:.2f} TL\n")

Var olan bir günlüğün ya da raporun sonuna satır eklemek:

with open("rapor.txt", "a", encoding="utf-8") as dosya:
    dosya.write("Yeni ölçüm eklendi\n")

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,
  • "puan" alanı sayı değil → ValueError,
  • Dosya boş,
  • Karakter kodlaması beklenenden farklı → UnicodeDecodeError gibi hatalar,
  • delimiter yanlış → beklenen sütunlar hiç oluşmayabilir.

13. haftada 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.

Üret: CSV satış özeti

Fonksiyon satırları DictReader ile okusun ve tutar alanını float ile sayıya çevirsin. İki değer döndürsün: toplam satış tutarı ve tutarı 100 TL ya da daha fazla olan satış sayısı. Dönüş biçimi (toplam, yuksek_satis_sayisi) olmalı. Beklenen sonuç (545.0, 2).

dosya = StringIO(veri), okuyucu = csv.DictReader(dosya) ve her kayıtta tutar = float(kayit["tutar"]) kullanabilirsiniz.

import csv
from io import StringIO

def csv_satis_ozeti(veri):
    dosya = StringIO(veri)
    okuyucu = csv.DictReader(dosya)

    toplam = 0
    yuksek_satis_sayisi = 0

    for kayit in okuyucu:
        tutar = float(kayit["tutar"])
        toplam = toplam + tutar

        if tutar >= 100:
            yuksek_satis_sayisi = yuksek_satis_sayisi + 1

    return toplam, yuksek_satis_sayisi

Kendi bilgisayarınızda deneyin

Bölümün başındaki puanlar.txt dosyasını oluşturun. Aynı klasöre şu programı kaydedip çalıştırın:

toplam = 0
adet = 0

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

print("Ortalama:", toplam / adet)

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ış: Bu seçenek satır sonlarıyla ilgilidir; BOM’u etkilemez.
  • C yanlış: Bu ayraç sorununu çözer; baştaki görünmez işareti kaldırmaz.
  • D yanlış: İkili kipte içerik metne hiç çevrilmez, byte olarak gelir; sorunu çözmez.
  • E yanlış: strip() boşluk kırpar; BOM bir boşluk karakteri değildir.

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 kendiliğinden kapatır.
  • "r" okur, "w" eski içeriği silip baştan yazar, "a" dosyanın sonuna ekler.
  • 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" metnin doğru çözülmesine yardım eder; başında BOM olan UTF-8 CSV için utf-8-sig gerekebilir.
  • 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 değildir; delimiter=";" gibi açıkça belirtilebilir.
  • Türkçe bölgesel ayarlı tablo programlarından gelen CSV’lerde noktalı virgül ve ondalık virgül sık görülür.
  • 12,5 gibi basit bir değeri replace() ile 12.5 yapabilirsiniz; binlik ayracı olan ya da başka bölgesel biçimde yazılmış sayılarda bu yöntem işe yaramaz.
  • csv.DictReader sütun adlarını anahtar yapar; bütün alanlar string olarak gelir.
  • 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 sistematik 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 metni nasıl etkilediğini bilir ve BOM sorununu tanır.
  • CSV’de sütun ayıracını delimiter ile belirler.
  • csv.DictReader ile okunan alanların metin olduğunu bilir 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ı bilir.
  • Okuma, dönüştürme ve hesaplama adımlarını birbirinden ayırır.
Back to top