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
- Program kapandıktan sonra da kalması gereken verileri dosyada saklamak
open()ile dosya açmak;read(),readline()veforile okumak;write()ile yazmakr,w,avexkiplerinin dosyaya etkisini ayırt etmekwithbloğunun dosyayı neden güvenle kapattığını açıklamak- Dosya imlecini
tell()veseek()ile izlemek; metin ve bayt farkını görmek pathlibile 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,avexkiplerinin sonuçlarını karşılaştıracağız. withbloğunun dosyayı neden kendiliğinden kapattığını göreceğiz.- Metin dosyasındaki karakter ve bayt ilişkisini inceleyeceğiz.
pathlibile 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.
open("notlar.txt","r",encoding="utf-8")
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.
tell() → 0tell() → 5tell() → 9tell() → 16read(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.
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.
write("Birinci\n")
write("İkinci\n")
Birinci
İkinci
gunluk.txt
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.
6 karakter · 8 bayt
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.
"notlar.txt"Göreli yol: çalışma dizininden başlar"veri/ogrenciler.csv"Göreli yol: alt klasörü de yazarız"/Users/ada/ders/notlar.txt"Mutlak yol: kök dizinden başlayan tam adresMutlak 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.
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ışı
Ayşe,80
Can,65
Çağlar,90
- Satırı okur,
strip()yapar - Boş satırı atlar
split(",")ile ad ve puan alır- Ortalamayı hesaplar
Ayşe: 80
Can: 65
Çağlar: 90
Ortalama: 78.3
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 dosyalardafordaha 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\nile 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—Pathnesnesinden yalnızca dosya adını alır, klasör kısmı olmadan.glob("*.txt")—*herhangi bir adla eşleşir;.mddosyası 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.
Yenive altında önceki üç satır - D. Dosya zaten var olduğu için
FileExistsErroroluş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.
ilkile aynı uzunluk - B.
0 - C.
FileNotFoundErroroluşur - D.
1 - E.
ValueErroroluş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ıpsplit("\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şlemlerdefor satir in dosyailk tercihtir. - Satırlar: Her satır
\nile biter.strip()bu karakteri temizler;split()satırı parçalara ayırır. Dosyadan gelen sayılar metindir veint()ile çevrilir.
- Yazmak:
write()vewritelines()satır sonu eklemez;\nbize 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:
withbloğ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 kipindeseek()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,stemvesuffixyolun parçalarını verir. - Eksik dosya: Bulunamayan dosya
FileNotFoundError,"x"ile açılan var olan dosyaFileExistsErrorverir. Hata yönetimini sonraki bölümde işleyeceğiz.
Bu Bölümü Bitiren Öğrenci
- Bir dosyayı
withile açar, okur ve yazar; dosyanın blok bitiminde kapandığını bilir. read(),readline(),readlines()veforile 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()ileprint()farkını vestrip()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()veseek(0)ile imleci izler; imleç sonda iken ikinciread()neden boş döndüğünü anlar.pathlibile 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.
Ayrıntılar için Python öğreticisinde dosya okuma ve yazma, open() belgesi ve pathlib belgesi yararlıdır.
← 07 · Modüller ve KütüphanelerYol haritası09 · Hata Yönetimi ve Loglama (hazırlanıyor)