Dosya İşlemleri

Verileri kalıcı olarak saklamak, okumak ve yazmak

← 07 · Modüller ve KütüphanelerYol haritası09 · Hata Yönetimi ve Loglama (hazırlanıyor)

Bölüm 8

Bu bölümde
  • Program kapandıktan sonra da kalması gereken verileri dosyada saklamak
  • open() ile dosya açmak; read(), readline() ve for ile okumak; write() ile yazmak
  • r, w, a ve x kiplerinin dosyaya etkisini ayırt etmek
  • with bloğunun dosyayı neden güvenle kapattığını açıklamak
  • Dosya imlecini tell() ve seek() ile izlemek; metin ve bayt farkını görmek
  • pathlib ile göreli ve mutlak yollarla çalışmak, bir klasördeki dosyaları listelemek
  • Dosyadan okunan satırları kayda çevirip sonucu yeni bir dosyaya yazmak

Notlar Program Kapanınca Nereye Gider?

Önceki bölümlerde notları listelerde ve sözlüklerde tuttuk. Bu yapılar programın belleğinde yaşar. Program bittiğinde bellek boşaltılır ve notlar da onunla birlikte kaybolur. Ertesi gün aynı programı açtığımızda her şeye baştan girmemiz gerekir.

Bellek Geçicidir, Dosya Kalıcıdır

Verinin program bittikten sonra da durmasını istiyorsak onu dosyaya yazarız. Dosya diskte durur; program kapansa da bilgisayar yeniden açılsa da içeriği yerinde kalır. Bir sonraki çalıştırmada programımız aynı dosyayı açıp verileri geri okuyabilir.

Bu bölümde dosya açmayı, okumayı ve yazmayı öğrenecek; sonunda notları bir dosyadan okuyup hesapladığımız sonucu başka bir dosyaya yazan küçük bir program kuracağız.

Bu Bölümde

  • Dosyayı açıp okuyacak, imlecin okuma sırasında nasıl ilerlediğini izleyeceğiz.
  • Dosyaya yazacak; w, a ve x kiplerinin sonuçlarını karşılaştıracağız.
  • with bloğunun dosyayı neden kendiliğinden kapattığını göreceğiz.
  • Metin dosyasındaki karakter ve bayt ilişkisini inceleyeceğiz.
  • pathlib ile dosya yollarını kuracak ve klasör içindeki dosyaları listeleyeceğiz.
  • Okuduğumuz satırları kayda çevirip rapor dosyası üreteceğiz.

Dosyayı Açmak ve Okumak

Bir dosyayla çalışmak üç adımdır: dosyayı açarız, içinde okuma ya da yazma yaparız, işimiz bitince kapatırız. Açma işini open() yapar.

open() Bir Dosya Nesnesi Verir

open() dosyanın içeriğini değil, o dosyayla çalışmamızı sağlayan bir dosya nesnesi döndürür. Okuma ve yazma işlemlerini bu nesnenin metotlarıyla yaparız.

Kip yazılmazsa dosya okumak için ("r") açılır. Kodlamayı encoding="utf-8" diye açıkça yazacağız; nedenini bu bölümde ilerleyince göreceğiz.

Önce Bir Dosya Oluşturalım

Okuyacağımız bir dosya gerekiyor. Aşağıdaki hücre notlar.txt adında bir dosya oluşturur ve içine her satırda bir öğrencinin adını ve puanını yazar. "w" kipi dosyayı yazmak için açar; kiplerin ayrıntısına birazdan döneceğiz.

Bu sayfadaki kod hücreleri tarayıcının içindeki sanal bir dosya sistemini kullanır. Hücrelerde oluşturduğumuz dosyalar bilgisayarınızın diskine yazılmaz.

Bütün İçeriği Okumak: read()

read() dosyanın tamamını tek bir string olarak döndürür. Hücreyi çalıştırmadan önce çıktının nasıl görüneceğini düşünün.

İlk print iki satırı alt alta gösterir. repr() ise metnin gerçek biçimini yazar: 'Ayşe,80\nCan,65\n'. Her satırın sonunda görünmeyen bir satır sonu karakteri (\n) vardır; print onu yeni satıra geçmek için kullanır.

İmleç Okudukça İlerler

Dosya nesnesi, nereye kadar okuduğumuzu bir imleçle hatırlar. Her okuma imleçten başlar ve imleci okuduğu yerin sonuna taşır. Mavi kutular o çağrıda okunan karakterlerdir, kırmızı çizgi imlecin yeridir.

read(4) sonrası tell() neden 5? Çünkü tell() karakteri değil bayt sayar ve ş iki bayttır. Kodlama başlığında ayrıntısına bakacağız.

Bir Satır Okumak: readline()

readline() imleçten başlayıp satır sonuna kadar olan bölümü döndürür. Her çağrı bir sonraki satıra geçer. Dosya bittikten sonra boş string döner. Hücrenin üç çıktısı ne olur?

Sırasıyla 'Ayşe,80\n', 'Can,65\n' ve '' yazılır. Üçüncü çağrıda okunacak satır kalmadığı için boş string döner; hata oluşmaz. Boş string, dosyanın sonuna geldiğimizi anlatır.

Bütün Satırları Liste Yapmak: readlines()

readlines() her satırı bir eleman yapan bir liste döndürür. Satır sonu karakterleri elemanların içinde kalır.

Satır Satır Dolaşmak: for

Dosya nesnesi doğrudan for ile dolaşılabilir. Döngü değişkeni her turda bir satır alır. Dosyanın tamamını belleğe bir liste olarak almaz; bu yüzden büyük dosyalarda da güvenle kullanılır.

strip() satırın başındaki ve sonundaki boşlukları, satır sonu karakteri dâhil, siler. print() zaten kendi satır sonunu eklediği için strip() kullanmazsak çıktıda her satırdan sonra bir boş satır görürüz.

Hangi Okuma Yöntemi?

Yöntem Döndürdüğü Ne zaman?
read() Tüm içerik, tek string Küçük bir dosyanın tamamı tek parça lazımsa
read(n) En fazla n karakter Dosyayı parça parça okumak gerekirse
readline() Tek satır, string Satırları elle, birer birer almak istiyorsak
readlines() Tüm satırlar, liste Satırlar üzerinde indeksle çalışacaksak
for satir in dosya Her turda bir satır Satır satır işlemlerin çoğunda; ilk tercihimiz

Satırı Kayda Çevirmek

Dosyadan gelen her şey metindir. "Ayşe,80" satırından ad ve puanı almak için satırı temizler, virgülden böler, puanı sayıya çeviririz.


split(",") iki parçalı bir liste verir ve ad, puan ile açılır. int(puan) olmadan toplam += puan satırı sayıya metin eklemeye çalışır ve TypeError verirdi.

Dosyaya Yazmak

Yazma, okumanın tersidir: dosyayı yazma kipinde açar ve dosya nesnesinin write() metodunu çağırırız.

write() Satır Sonunu Kendisi Eklemez

write() verdiğimiz metni olduğu gibi yazar. Satırı bitirmek istiyorsak \n karakterini biz ekleriz. Aşağıdaki hücrede dosyaya ne yazılır?

Birinci ve İkinci aynı satırda yan yana görünür: Birinciİkinci. İlk write() çağrısında \n olmadığı için ikincisi aynı satırdan devam etti. Üçüncü ise ikinci çağrının \n karakteri sayesinde yeni satıra yazıldı.

Birden Çok Satır Yazmak

Satırları bir listede tutuyorsak writelines() hepsini sırayla yazar. Bu metot da satır sonu eklemez; her string’in sonuna \n koymak bize kalır. Bir diğer yol, dosyaya yazdırmak için print() işlevinin file parametresini kullanmaktır: print() satır sonunu kendisi ekler.

Sayıları Yazmak: Önce Metne Çevirmek

write() yalnızca string kabul eder. Sayı yazmak istiyorsak f-string ya da str() ile önce metne çeviririz. Aşağıdaki hücre bilerek hata veriyor; mesajı okuyun.

Hata mesajı write() argümanının string olması gerektiğini, int verildiğini söyler. Düzeltmek için dosya.write(f"{puan}\n") yazarız.

Dosya Kipleri

open() çağrısındaki ikinci argüman dosyanın hangi amaçla açılacağını belirler. Aynı dosya üzerinde kipe göre çok farklı sonuçlar oluşur.

r, w, a ve x

Kip Amaç Dosya yoksa Dosya varsa
"r" Okumak (varsayılan) FileNotFoundError İçerik korunur, imleç başta
"w" Yazmak Oluşturur İçeriği siler
"a" Sona eklemek Oluşturur İçerik korunur, yazı sona eklenir
"x" Yeni dosya oluşturmak Oluşturur FileExistsError

w Eski İçeriği Siler

"w" ile açılan dosya, içinde ne olduğuna bakılmadan hemen sıfırlanır. Yazma işlemi yapmasak bile açılış anında eski içerik gider. Bir dosyaya mevcut içeriği koruyarak eklemek istiyorsak "a" kullanırız.


Dikkat

Bir dosyayı "w" ile açmadan önce kendinize şunu sorun: eski içerik kalmalı mı? Cevap evetse "a" kullanın. Yanlış kip seçmenin bedeli dosyanın kaybolmasıdır.

Üç Kipi Sırayla Denemek

Hücredeki dört with bloğu aynı dosyayı sırayla "w", "a", "w" ve "r" kipiyle açıyor. Son print dosyada hangi satırları gösterir?

Yalnızca Üçüncü satır görünür. İkinci blok "a" ile sona ekleme yaptı, ancak üçüncü blok dosyayı yeniden "w" ile açtığı için hem birinci hem ikinci satır silindi. Hücreyi bir kez daha çalıştırsanız da sonuç değişmez: "w" her açılışta dosyayı sıfırlar.

Günlük Tutmak: a ile Ekleme

"a" kipi, her çalıştırmada kayıt eklemek istediğimiz günlük dosyaları için uygundur. Hücreyi birkaç kez çalıştırın; satırlar silinmez, birikir.

x: Var Olan Dosyayı Korumak

"x" kipi yalnızca yeni bir dosya oluşturur. Dosya zaten varsa hiçbir şeyi bozmadan FileExistsError verir. Önemli bir dosyanın yanlışlıkla ezilmesini önlemek için kullanışlıdır.

Hem Okuma Hem Yazma: +

Kipe + eklersek dosya hem okunabilir hem yazılabilir olur. Üç + kipinin açılışta yaptığı iş temel kiplerle aynıdır.

Kip Amaç Dosya yoksa Dosya varsa
"r+" Oku ve yaz FileNotFoundError İçerik korunur, imleç başta
"w+" Yaz ve oku Oluşturur İçeriği siler
"a+" Ekle ve oku Oluşturur İçerik korunur, yazı hep sona eklenir

r+ Araya Eklemez, Üzerine Yazar

r+ ile imleç başta başlar. write() imlecin bulunduğu yerden itibaren var olan karakterlerin üzerine yazar; araya ekleme yapmaz. Hücrede dosya Merhaba iken başına XY yazılırsa ne olur?

Sonuç XYrhaba olur. XY baştaki Me karakterlerinin yerine geçti, geri kalan metin yerinde kaldı. seek(0) imleci yazdıktan sonra başa aldığı için read() bütün dosyayı gösterdi; bu satırı çıkarırsanız read() boş döner, çünkü imleç yazılan metnin sonunda kalır.

Metin Mi, İkili Mi?

Kipe "t" ya da "b" ekleyebiliriz. Metin kipi ("t", varsayılan) baytları karakterlere çevirir ve string döndürür. İkili kip ("b") baytlara dokunmaz; resim, ses ve PDF gibi metin olmayan dosyalar için kullanılır. İkili kipte kodlama belirtilmez ve okunan değer bytes olur.

Dosyayı Kapatmak ve with

Açtığımız dosya işletim sisteminin sınırlı sayıda verdiği bir kaynağı tutar. İşimiz bitince dosyayı kapatmak gerekir.

Neden Kapatmalıyız?

write() çağrıları verinin hemen diske gitmesini sağlamaz. Yazılan metin önce bellekte küçük bir tamponda toplanır. close() çağrıldığında tampondakiler diske aktarılır ve dosya serbest kalır. Kapatmayı unutursak veri diske hiç ulaşmayabilir, dosya başka programlar tarafından kullanılamayabilir.

Elle Kapatmak: close()

Dosya nesnesinin closed özelliği dosyanın kapalı olup olmadığını gösterir. Önce açıkken, sonra close() çağrısından sonra bakalım.

Araya Hata Girerse

open() ile close() arasında hata çıkarsa program durur ve close() satırına ulaşılmaz. Hücre hatayı try/except ile yakalıyor; bu yapıyı bir sonraki bölümde işleyeceğiz. Burada yalnızca close() satırının atlandığına bakıyoruz.


Dosya açık kaldı. Küçük bir betikte fark edilmeyebilir; uzun süre çalışan bir uygulamada açık dosyalar birikir ve sınırlı kaynaklar tükenebilir.

with Bloğu: Hata Olsa da Kapanır

with bloğu dosyanın kapatılmasını Python’a bırakır. Blok normal biçimde de bitse, içinde bir hata da çıksa dosya kapatılır.


Önceki hücreyle aynı hatayı yaşadık, ama bu kez dosya.closed değeri True. Kapatmayı hatırlamak zorunda olmadığımız için with dosya işlemlerinde standart yoldur; bu bölümün geri kalanında dosyaları hep with ile açacağız.

Metin ve Kodlama

Metin dosyası aslında bayt dizisidir. Hangi baytın hangi karaktere karşılık geldiğini bir karakter kodlaması belirler. encoding="utf-8" yazmamızın nedeni bu eşleşmeyi açıkça seçmektir.

Karakter ve Bayt Aynı Şey Değildir

UTF-8’de İngilizce harfler tek bayttır; Ç, ğ, ş, ı gibi Türkçe harfler ise iki bayt yer kaplar. Çağlar yazısı altı karakter olmasına rağmen dosyada sekiz bayttır. Önceki imleç şemasında tell() değerinin karakter sayısından büyük çıkmasının nedeni de buydu.

Yanlış Kodlamayla Okumak

Bir dosya UTF-8 ile yazılıp başka bir kodlamayla okunursa baytlar farklı karakterlere çevrilir. Aşağıdaki hücre aynı sekiz baytı önce doğru, sonra Türkçe Windows’ta kullanılan cp1254 kodlamasıyla çözüyor.

Kodlamayı yazmazsak Python işletim sisteminin varsayılanını kullanabilir. Aynı program başka bir bilgisayarda farklı çalışabilir. Bu yüzden metin dosyalarında her zaman encoding="utf-8" yazıyoruz.

İmleç: tell() ve seek()

Dosya imleci okuma ve yazmanın nereden devam edeceğini belirler. İki metotla bu konumu hem öğrenebilir hem değiştirebiliriz.

tell(): İmlecin Yeri

tell() imlecin başlangıçtan itibaren bayt cinsinden konumunu döndürür. Hücrede Ayşe yazısının dört karakter olmasına rağmen read(4) sonrası değer 5’tir, çünkü ş iki bayttır.

seek(): İmleci Başa Almak

read() bir kez çağrıldığında imleç dosyanın sonuna gelir. İkinci read() okunacak bir şey bulamaz ve boş string döndürür. seek(0) imleci başa taşır; böylece dosyayı yeniden okuyabiliriz.

Metin Kipinde Sınır

Metin kipinde bir bayt sayısı kadar ileri ya da geri gitmek güvenli değildir; çünkü iki baytlık bir harfin ortasına düşebilirsiniz. Bu yüzden seek() metin dosyalarında yalnızca iki biçimde kullanılır: seek(0) başa, seek(0, 2) sona gider. Sondan geriye gitmeyi deneyen hücre hata verir.

İkili kipte ("rb") bu sınır yoktur: bayt konumlarıyla serbestçe çalışabilirsiniz.

Dosya Yolları

Şimdiye kadar yalnızca notlar.txt gibi kısa adlar yazdık. Bir dosya başka bir klasördeyse programın onu nasıl bulacağını yolla anlatırız.

Dosya Nerede Aranır?

Python göreli bir yol gördüğünde dosyayı çalışma dizininde arar: programın çalıştırıldığı klasör. Şemada program.py dosyası ders/ klasöründen çalıştırılıyor. Bu durumda notlar.txt doğrudan bulunur, ogrenciler.csv için veri/ klasörünü de yazmamız gerekir.


Mutlak yol işe yarar ama başka bilgisayara taşıdığımızda geçersiz kalır; kullanıcı adı ve klasör düzeni her makinede farklıdır. Proje içindeki dosyalar için göreli yol daha taşınabilirdir.

pathlib ile Yol Kurmak

Windows klasörleri \ ile, macOS ve Linux / ile ayırır. Yolu elle string olarak birleştirirsek program yalnızca bir sistemde çalışabilir. pathlib modülündeki Path, ayırıcıyı çalışılan sisteme göre seçer. Yolu / işleciyle birleştiririz.


Eski yöntem: os.path.join()

Eski kodlarda aynı iş os.path.join("veri", "notlar.csv") ile yapılır. Sonucu aynıdır, ancak Path hem yolu kurar hem de dosya adı, uzantı ve varlık denetimi gibi işleri tek nesnede toplar. Yeni yazdığımız kodda pathlib kullanıyoruz.

Klasör Oluşturmak ve Dosyaları Listelemek

mkdir(exist_ok=True) klasörü oluşturur, varsa hata vermez. write_text() ve read_text() küçük dosyaları tek satırda yazar ve okur. glob("*.txt") desene uyan dosyaları bulur.


bilgi.md desene uymadığı için listede görünmez. Klasördeki her şeyi görmek için klasor.iterdir() kullanılır.

Dosya Bulunamazsa

Yol yanlışsa ya da dosya hiç oluşturulmamışsa open() FileNotFoundError verir. Hata mesajı aranan yolu da yazar; ilk bakılacak yer burasıdır.


Dosyanın olmaması beklenen bir durumsa hatayı yakalayıp anlamlı bir mesaj verebiliriz. try/except yapısını bir sonraki bölümde ayrıntılı işleyeceğiz.

Uygulama: Not Raporu

Öğrendiklerimizi birleştirelim: notları bir dosyadan okuyacak, ortalamayı hesaplayacak ve sonucu başka bir dosyaya yazacağız.

Programın Akışı

Notları Okumak

Girdi dosyasında bir de boş satır bırakıldı; gerçek dosyalarda bu sık görülür. Program boş satırı atlıyor ve her satırdan ad ile puanı alıp bir sözlüğe koyuyor.

Raporu Yazmak

Okuma işi bitince dosya kapandı; rapor için yeni bir with bloğu açıyoruz. Bu hücre, önceki hücrenin oluşturduğu notlar sözlüğünü kullanır; önce onu çalıştırın.

Alıştırmalar

Alıştırma 1: Satırları Say

notlar.txt dosyasında kaç öğrenci kaydı olduğunu bulun. Dosyayı for ile satır satır dolaşın ve her satırda sayacı artırın.


  • for satir in dosya — dosya nesnesi doğrudan dolaşılır; her turda bir satır gelir ve sayaç bir artar.
  • len(dosya.readlines()) de aynı sonucu verir, ancak bütün satırları önce belleğe liste olarak alır. Büyük dosyalarda for daha uygundur.

Alıştırma 2: Günlüğe Ekle

Bir program her çalıştığında calisma.log dosyasına bir satır eklemeli, önceki satırları silmemelidir. Boşluğa uygun kipi yazın ve hücreyi üç kez çalıştırın. Her çalıştırmada satır sayısı artmalıdır.


  • "a" — dosya yoksa oluşturur, varsa eski satırları korur ve yeni satırı sona ekler. Hücreyi her çalıştırdığınızda satır sayısı bir artar.
  • "w" yazsaydık her çalıştırmada dosya sıfırlanır ve her zaman tek satır görürdük.

Alıştırma 3: Alfabetik Sırala

adlar.txt dosyasındaki isimleri alfabetik sıraya dizip sirali.txt dosyasına yazın. Her ad ayrı satırda olmalıdır.


  • sorted(...) — satırları sıralı yeni bir liste yapar; her satır \n ile bittiği için satır sonları korunur.
  • writelines(sirali) — listeyi sırayla yazar; satır sonlarını elemanlar zaten taşıdığı için ekleme gerekmez.

sorted() karakter kodlarına göre sıralar, Türkçe alfabeye göre değil. Çağlar gibi bir ad bu yüzden listenin sonuna düşebilir; Türkçe sıralama için ayrı bir yöntem gerekir.

Alıştırma 4: En Çok Kelimeli Satır

not.txt dosyasında kelime sayısı en yüksek olan satırı bulun ve kelime sayısıyla birlikte yazın.


  • satir.split() — argümansız çağrılınca metni boşluklara göre böler; len() kelime listesinin uzunluğunu verir.
  • en_cok = kelime_sayisi — yeni rekor bulunduğunda sayıyı ve satırı birlikte güncelleriz.

Alıştırma 5: .txt Dosyalarını Listele

odevler klasöründeki .txt dosyalarının adlarını alfabetik sıraya dizip liste.txt dosyasına satır satır yazın. .md dosyası listede olmamalıdır.


  • yol.name — Path nesnesinden yalnızca dosya adını alır, klasör kısmı olmadan.
  • glob("*.txt") — * herhangi bir adla eşleşir; .md dosyası desene uymadığı için listeye girmez.

Kendini Sına

Kodları çalıştırmadan önce çıktıları tahmin edin. Ardından cevabınızı ve gerekçenizi karşılaştırın; yanlış şıkların hangi kavram karışıklığından kaynaklandığına dikkat edin.

Soru 1

with open("notlar.txt", "r", encoding="utf-8") as dosya: yazımının, open() ve close() ile elle çalışmaya göre avantajı nedir?

  • A. Dosya yoksa kendiliğinden oluşturur
  • B. Dosyayı belleğe tümüyle yükleyerek okumayı hızlandırır
  • C. Kodlama belirtmeyi gereksiz kılar
  • D. Satırları kendiliğinden listeye böler
  • E. Blok bittiğinde, içinde hata çıksa bile dosyayı kapatır

Doğru: E. with bloğundan çıkılırken dosya her durumda kapatılır. A için "w", "a" ya da "x" kipi gerekir; with dosya oluşturmaz. B yanlıştır, with okuma hızını değiştirmez. C yanlıştır; kodlama açıkça yazılmalıdır. D için readlines() ya da for döngüsü kullanılır.

Soru 2

odev.txt dosyasında üç satır var. Aşağıdaki kod çalıştırıldıktan sonra dosyada ne bulunur?

with open("odev.txt", "w", encoding="utf-8") as dosya:
    dosya.write("Yeni\n")
  • A. Yalnızca Yeni
  • B. Önceki üç satır ve sonuna Yeni
  • C. Yeni ve altında önceki üç satır
  • D. Dosya zaten var olduğu için FileExistsError oluşur
  • E. Dosya değişmez, çünkü hiçbir şey okunmadı

Doğru: A. "w" kipi dosyayı açar açmaz içeriği siler; sonra Yeni yazılır. B "a" kipinin sonucudur. C yeni içeriğin başa eklendiğini varsayar; böyle bir kip yoktur. D "x" kipinin davranışıdır. E yanlıştır: yazma işlemi olmasa bile "w" ile açmak dosyayı boşaltır.

Soru 3

with open("deneme.txt", "w", encoding="utf-8") as dosya:
    dosya.write("Ay")
    dosya.write("şe")

with open("deneme.txt", "r", encoding="utf-8") as dosya:
    print(repr(dosya.read()))
  • A. 'Ay\nşe\n'
  • B. 'Ay şe'
  • C. ['Ay', 'şe']
  • D. 'Ayşe'
  • E. None

Doğru: D. write() satır sonu eklemez; iki çağrı arka arkaya yazılır ve read() string döndürür. A write() ya da print() ile her çağrıdan sonra satır sonu eklendiğini varsayar. B aralarına boşluk koyar. C readlines() benzeri bir liste bekler, ayrıca satır sonu da olurdu. E write() dönüş değerinin yazdırıldığını varsayar; oysa okunan içerik yazdırılıyor.

Soru 4

with open("notlar.txt", "r", encoding="utf-8") as dosya:
    ilk = dosya.read()
    ikinci = dosya.read()
    print(len(ikinci))

notlar.txt dosyası boş değildir. Çıktı nedir?

  • A. ilk ile aynı uzunluk
  • B. 0
  • C. FileNotFoundError oluşur
  • D. 1
  • E. ValueError oluşur

Doğru: B. İlk read() imleci dosyanın sonuna taşır. İkinci read() okunacak karakter bulamaz ve hata vermeden boş string döndürür; uzunluğu 0’dır. A imlecin kendiliğinden başa döndüğünü varsayar; başa dönmek için seek(0) gerekir. C dosya var olduğu için doğru değildir. D ve E için bir neden yoktur.

Soru 5

ogrenciler.txt dosyasının ilk satırı Çağlar,90\n. Aşağıdaki kodun çıktısı nedir?

with open("ogrenciler.txt", "r", encoding="utf-8") as dosya:
    dosya.read(3)
    print(dosya.tell())
  • A. 2
  • B. 3
  • C. 4
  • D. 5
  • E. 6

Doğru: D. read(3) üç karakter okur: Ç, a ve ğ. tell() karakteri değil bayt sayar: Ç iki, a bir ve ğ iki bayttır; toplam beştir. B karakter sayısını bayt sayısıyla karıştırır. A, C ve E ise harflerin bayt boyutlarını yanlış toplamaktan gelir.

Soru 6

from pathlib import Path

yol = Path("veri") / "notlar.csv"
print(yol.stem, yol.suffix)
  • A. notlar .csv
  • B. veri notlar.csv
  • C. notlar.csv .csv
  • D. notlar.csv veri
  • E. veri .csv

Doğru: A. stem dosya adının uzantısız hâlini (notlar), suffix ise uzantıyı (.csv) verir; print ikisini boşlukla ayırır. B ve D klasör adını sonuca katar; klasör parent ile alınır. C stem yerine name yazılmış gibi düşünür. E klasörü ve uzantıyı karıştırır.

Soru 7

Boyutu çok büyük olabilecek bir günlük dosyasındaki her satırı sırayla işlemek istiyoruz. Hangi yaklaşım en uygundur?

  • A. dosya.read() ile tamamını alıp split("\n") yapmak
  • B. dosya.readlines() ile liste almak ve indeksle dolaşmak
  • C. for satir in dosya: ile satırları birer birer almak
  • D. Dosyayı "w" kipiyle açıp okumak
  • E. Her satır için dosyayı yeniden açmak

Doğru: C. for döngüsü satırları gerektikçe okur; dosyanın tamamı belleğe alınmaz. A ve B bütün içeriği belleğe yükler. D yanlıştır, "w" dosyayı boşaltır. E hem gereksiz hem de yavaştır; imleç her açılışta başa döner.

Kod Yazma: En Yüksek Not

notlar.txt dosyasının her satırı ad,puan biçiminde. en_yuksek(dosya_yolu) fonksiyonunu yazın: en yüksek puanı alan öğrencinin (ad, puan) demetini döndürsün. Boş satırları atlasın; puan sayı olarak karşılaştırılmalıdır.

Dosya with ile açılır ve for ile dolaşılır. Boş satır continue ile atlanır. Puan int() ile sayıya çevrilmeden karşılaştırılsaydı metinler alfabetik sıralanırdı ("9" > "80"). en_iyi başta None olduğu için ilk geçerli kayıt doğrudan seçilir.

Özet ve Kazanımlar

Kısa Özet

  • Kalıcılık: Bellekteki veriler program bitince kaybolur; dosyaya yazılanlar kalır.
  • Açmak: open(yol, kip, encoding="utf-8") bir dosya nesnesi döndürür. Kip yazılmazsa dosya okumak için açılır.
  • Okumak: read() tüm içeriği, readline() bir satırı, readlines() satırların listesini verir. Satır satır işlemlerde for satir in dosya ilk tercihtir.
  • Satırlar: Her satır \n ile biter. strip() bu karakteri temizler; split() satırı parçalara ayırır. Dosyadan gelen sayılar metindir ve int() ile çevrilir.

  • Yazmak: write() ve writelines() satır sonu eklemez; \n bize aittir. write() yalnızca string kabul eder.
  • Kipler: "r" okur, "w" yazar ve eski içeriği siler, "a" sona ekler, "x" yalnızca yeni dosya oluşturur. + okuma ve yazmayı birlikte açar.
  • Kapatmak: with bloğu dosyayı hata olsa bile kapatır. Tamponda bekleyen veri kapanırken diske yazılır.
  • Kodlama: Metin dosyası baytlardan oluşur. encoding="utf-8" yazmak aynı dosyanın her makinede aynı okunmasını sağlar.

  • İmleç: Her okuma ve yazma imleçten başlar. tell() bayt cinsinden konumu verir, seek(0) başa döner. Metin kipinde seek() yalnızca başa ve sona gitmek için güvenlidir.
  • Yollar: Göreli yol çalışma dizininden başlar, mutlak yol kökten. Path("veri") / "notlar.txt" yolu her sistemde doğru kurar.
  • Klasörler: mkdir(exist_ok=True) klasör oluşturur, glob("*.txt") desenle dosya bulur; name, stem ve suffix yolun parçalarını verir.
  • Eksik dosya: Bulunamayan dosya FileNotFoundError, "x" ile açılan var olan dosya FileExistsError verir. Hata yönetimini sonraki bölümde işleyeceğiz.

Bu Bölümü Bitiren Öğrenci

  • Bir dosyayı with ile açar, okur ve yazar; dosyanın blok bitiminde kapandığını bilir.
  • read(), readline(), readlines() ve for ile okumanın farkını açıklar, duruma uygun olanı seçer.
  • "r", "w", "a" ve "x" kiplerinin dosya var olmadığında ve var olduğunda ne yaptığını söyler.
  • Satır sonu karakterini, write() ile print() farkını ve strip() ile temizlemeyi doğru kullanır.

  • Metin dosyalarında encoding="utf-8" yazmanın gerekçesini ve karakter ile bayt farkını açıklar.
  • tell() ve seek(0) ile imleci izler; imleç sonda iken ikinci read() neden boş döndüğünü anlar.
  • pathlib ile yol kurar, klasör oluşturur ve desene uyan dosyaları listeler.
  • Dosyadan okuduğu satırları kayda çevirir, sonuç raporunu başka bir dosyaya yazar.
Başvuru

← 07 · Modüller ve KütüphanelerYol haritası09 · Hata Yönetimi ve Loglama (hazırlanıyor)

Başa dönüş