Bir dosyanın içeriğini okumak istediğinizde ilk başvuracağınız yer Python’ın “open” fonksiyonu olmalı. Dosyaya bir dosya adı verdiğinizde, hem düz metin hem de ikili formatlarda veri okumanıza ve yazmanıza olanak tanıyan çok yönlü bir nesne elde edersiniz.
Bu örnekler; farklı modları, ara belleğe alma, kodlama ve daha fazlasını destekleyen bu işlevin ne kadar esnek olduğunu göstermekte.
Bir Dosyayı Açın ve İçeriğini Okuyun
open() fonksiyonunun oldukça karmaşık bir imzası var ancak en basit durumlarda, bunu bir metin dosyasını açmak için şu şekilde kullanabilirsiniz:
f = open(filename)
Varsayılan olarak Python, bu dosyayı okuma modunda açar; yani dosyadan yalnızca okuma yapabilirsiniz. Bu da yapılandırma, statik veri gibi dosyalar için ideal olarak değerlendiriliyor. Ayrıca bu yöntem, durumu kısa ve hatırlanması kolay hâle getiriyor.
open() fonksiyonu, bir dosyanın tüm içeriğini okumak da dâhil olmak üzere çeşitli görevleri gerçekleştirmek için kullanabileceğiniz bir dosya nesnesi döndürür:
f = open("/usr/share/dict/words")
text = f.read()
print(text)
Bu basit kod parçasının, dosya mevcut değilse Python’ın bir istisna oluşturmasına neden olacağını unutmayın:

Varlığı garanti edilen bir dosya, çalıştırdığınız betik olarak nitelendiriliyor. Python, bu betiği özel “__file__” değişkeninde kullanıma sunar. Bu sayede kendi kaynak kodunu yazdırmak için bir betik yazmak çok kolay olur. Bu betik, quine olarak da bilinir:
f = open(__file__)
text = f.read()
print(text)

NOT: Eğer gerçekten katı davranırsanız, bu tam olarak bir quine değil çünkü bir dosyayı okumak hile yapmak olarak kabul ediliyor.
Bir Dosyayı Otomatik Olarak Kapatmak için “with” Anahtar Sözcüğünü Kullanın
Python bir dosyayı açtığında, sistem kaynaklarını o dosyaya ayırır ve bu kaynakları daha sonra okuma ve yazma gibi gelecekteki işlemler için kullanır. Programınız sonuna kadar çalışırsa, Python bu kaynakları temizleyerek sisteminizde çalışabilecek diğer işlemlerin kullanımına sunmalı. Ancak bu garanti edilemez. Bu nedenle kaynakların doğru şekilde temizlendiğinden her zaman emin olmalısınız. Bunu yapmanın en basit yolu, dosyanızla çalışmayı bitirdiğinizde close() metodunu açıkça çağırmak olabilir:
f = open("/usr/share/dict/words")
text = f.read()
f.close()
İPUCU: Bir dosyayı mümkün olduğunca en kısa sürede kapatmayı hedefleyin. Örneğin; bir dosyayı açıp içeriğini okuduktan sonra işliyorsanız, içeriğini okuduktan sonra dosyayı kapatmaya çalışın. Bir değişkene okuduğunuz verileri işlerken dosyayı açık tutmanıza gerek yok.
Ancak yine de sorunlar ortaya çıkabilir: close() çağrısı düzgün çalışmazsa ne olur? Bu sorunu aşmak için “with” anahtar sözcüğünü kullanmalısınız. Bu, sardığı blok için bir bağlam yöneticisi oluşturur ve dosya kaynaklarının serbest bırakılmasını sağlar:
with open("/usr/share/dict/words") as f:
text = f.read()
Bir Dosyayı Okuyarak ve Yazarak Kopyalayın
Çeşitli Python kütüphaneleri bir dosyayı kopyalamanın yollarını sağlar. Bu nedenle bu örnek, tamamen açıklayıcı bir nitelikte; open işlevinin ikinci argümanı olan mode’un kullanımını gösterir. Bu argüman, open işlevine dosyayı nasıl kullanmayı planladığınızı bildirir. Aşağıdaki karakterlerin herhangi bir geçerli kombinasyonunu kullanabilirsiniz:
| Karakter | Anlam |
|---|---|
| r | Oku |
| w | Yaz |
| x | Oluştur ve yaz |
| a | Ekle |
| b | İkili |
| t | Metin |
| + | Güncelleme |
Varsayılan rt modu (metin dosyası okuma); bu nedenle bu makaledeki ilk örnek beklendiği gibi çalışmış durumda. Okuduğunuz dosyayı kopyalamak için yazmak üzere “w” modunu kullanarak ikinci bir dosya açmanız gerekir. Ayrıca okuma ve yazma işlemlerinin ikili verileri dikkate almasını sağlamak için her ikisi için de “b” modunu kullanmanız gerekir.
source = "./image.jpg"
target = "./a-copy-of-image.jpg"
with open(source, "rb") as src, open(target, "wb") as tgt:
buffer = src.read()
tgt.write(buffer)
with bloku, her iki dosyada da çalışır; bu nedenle tamamlandığında dosyaları otomatik olarak kapatır.
NOT: Python’ın open fonksiyonu size bir dosyanın içeriğine düşük seviyede erişim sağlarken, os modülü dosyalar ve dosya sistemi üzerinde işlem yapan birçok üst seviye fonksiyon sağlar.
Yeni Bir Metin Dosyası Oluşturun
Yeni bir dosya oluşturmak için mod argümanını da kullanabilirsiniz. Ancak aynı ada sahip ve hâlihazırda var olabilecek herhangi bir dosyayı koruyabilirsiniz:
open(filename, "x")
Aynı ada sahip bir dosya zaten mevcutsa, bu açık çağrı bir FileExistsError istisnası oluşturacak. Bu ise dosyanın varlığını açıkça kontrol etme ihtiyacını ortadan kaldıran iyi bir savunma önlemi olarak öne çıkıyor:
# Uyarı: Bunu yapmayın!
import os.path
filename = "example.txt"
if os.path.isfile(filename):
print("Sorry, file already exists")
else:
with open(filename, "w") as f:
# ...
Ancak biraz daha az kod yazmak zorunda kalmanın yanı sıra, “x” modunu kullanmak için daha da iyi bir sebep var: Yarışma durumunu önler. Yukarıdaki örneği ele alalım: Bu örnekte, dosyanın var olup olmadığını kontrol eden bir ifade (if os.path.isfile(filename)), ardından dosyayı yazmak üzere açan başka bir ifade (with open(filename, “w”) as f) bulunuyor. Bu iki ifade arasında başka bir işlem bu dosyayla herhangi bir işlem yaparsa, felaket meydana gelebilir.
Bir dosyayı oluşturma modunda açmak, tek bir ifadenin dosyayı kontrol edip açmaktan sorumlu olması nedeniyle felaketi önleyebilir. Ya başarısız olur ve mevcut dosya korunur ya da başarılı olur ve bu sırada başka hiçbir işlem aynı isimde başka bir dosya oluşturamaz.
Ekleme Yoluyla Bir Günlük Dosyasına Yazın
Varsayılan olarak, yazma modunda açtığınız bir dosya önce kesilir. Bu nedenle içeriğinin üzerine yazılır. Bunun yerine bir dosyaya eklemek için ekleme modunu kullanabilirsiniz:
log = open("file.log", "a")
Python’da günlük kaydı, birçok zahmetli ayrıntıyla ilgilenen günlük kaydı modülüyle daha iyi yönetilir. Fakat örnek olması açısından aşağıdakine benzer bir kod kullanarak bir dosyaya günlük kaydı yapabilirsiniz:
def startup():
print("Just a dummy")
def main():
print("Doing the main thing")
return 42
def log(msg):
logfile.write(msg + "\n")
logfile = open("file.log", "w")
log("starting startup")
startup()
log("startup finished")
log("starting main")
ret = main()
log("main finished: " + str(ret))
logfile.close()
Dosya Kaydetmeyi Kontrol Etmek için Arabelleğe Alma Özelliğini Kullanın
Aynı dosyayı sürekli yeniden açıp kaydetmekten kaçınmak için günlük kaydı örneği, genel bir değişken ve uzun ömürlü bir dosya tanıtıcısı kullanır. Bu, basit bir örnekte kabul edilebilir görünse de gerçek hayatta programınız süresiz olarak çalışabilir ve bu günlük dosyasını istediğiniz zaman kontrol etmek isteyebilirsiniz.
while True:
log(random.random())
input("Press Enter to continue")
Bu kod, uzun süredir devam eden bir işlemin periyodik günlük kaydını yapmayı taklit eder. Başka bir satırın günlüğe kaydedilmesini istediğinizde Enter tuşuna basarak günlük kaydını kontrol edebilirsiniz. Ancak bunu çalıştırdığınızda büyük bir kusur fark edeceksiniz: Birkaç kez Enter tuşuna basıp günlük dosyasını kontrol ederseniz, dosyaya hiçbir şey yazılmadığını göreceksiniz!
İPUCU: tail komutu (özellikle tail -f komutu), bir günlük dosyasındaki değişiklikleri gerçek zamanlı olarak izlemenize yardımcı olabilir.
Enter tuşuna yeterince basarsanız, sonunda bazı sonuçlar görmelisiniz çünkü çıktı Python’ın varsayılan ara bellek boyutunu aşmış olacak.
Neyse ki, bu gibi durumlar için ara belleğe alma politikasını tanımlamanıza olanak tanıyan bir argüman mevcut. Bir günlük dosyası söz konusu olduğunda izlenecek en harika yaklaşım, satır ara belleğe alma olur.
Önceki örneği ufak bir değişiklikle çalıştırmayı deneyin:
logfile = open("file.log", "w", 1)
Üçüncü argüman olan 1, satır ara belleğine sahip olmayı belirtir. Bu özellik etkinleştirildiğinde, log() işlevi dosyaya yazarken sonuna yeni satır karakteri eklendiğinden, bu işlev her çalıştırıldığında günlük dosyasının güncellendiğini görmelisiniz.
Uygun UTF-8 Desteği için Bir Kodlama Belirleyin
Karakter kodlaması, genellikle karmaşık bir konu olarak görülse de günümüzde UTF-8’in yaygın kullanımı sayesinde bu konuda endişelenmeye çoğu zaman gerek kalmıyor. Ancak bazı eski sistemler farklı kodlamalar kullanıyor olabilir ve gelecekte nelerle karşılaşacağınızı bilemezsiniz. Kodlamayla ilgili hatalar büyük sorunlara neden olabilir.
UTF-16, belirli metin türleri için daha verimli olan UTF-8’e alternatif bir kodlama olarak öne çıkıyor. İngilizce yazılmış metinlerin çoğu UTF-8 için daha uygun. Ancak diğer dillerde yazılmış metinler veya emojilerle dolu bir dosya gibi sembol koleksiyonları, UTF-16 olarak depolandığında daha küçük boyutlu olurlar.
Standart açma yaklaşımını kullanarak bir UTF-16 dosyasını açmaya çalışırsanız bir hata mesajı görürsünüz:

open işlevi (birkaç istisna dışında) varsayılan olarak UTF-8 kodlamasını bekler. Bu nedenle UTF-16 dosyasını açmak için kodlamayı belirtmeniz gerekir:
f = open("../utf16-file.txt", encoding="utf-16")
Adlandırılmış bir argüman kullanarak, mod ve ara belleğe alma argümanlarını varsayılan değerleriyle bırakabilirsiniz. Alternatif olarak, bunlar için varsayılan (veya özel) değerler sağlayabilirsiniz:
f = open("../utf16-file.txt", "r", -1, "utf-16")
UTF-8 formatında bir dosya açıyor olsanız bile, kodlamayı bu argümanı kullanarak açıkça belirtmeniz iyi bir fikir olabilir. Bazı işletim sistemleri (örneğin Windows) UTF-8 dışındaki bir kodlama kullanabilir. Bu nedenle varsayılana güvenmemeniz akıllıca olacak.
Hatalı Biçimlendirilmiş Dosyaları Hatalar Parametresini Kullanarak Yönetin
Bir kodlamayı belirtmekte fayda var ancak bu her zaman mümkün olmayabilir. Bunun yanı sıra kodlama hataları durumunda open fonksiyonu, başarısız olmak zorunda değil; davranışını çeşitli seçenekler arasından seçmek için errors argümanını kullanabilirsiniz.
Varsayılan değer “strict” ve bu bir istisna oluşturur. Fakat “ignore” ile bu tür hataları tamamen yok sayabilirsiniz:
f = open("../utf16-file.txt", errors='ignore')
Olumsuz tarafı, farkında olmadan bozuk verilerle uğraşıyor olmanız olabilir. Bununla başa çıkıp çıkamayacağınız, verilerinizin niteliğine bağlı olacak.
Yaygın bir alternatif de geçersiz karakterleri, eksik olduklarını belirten bir karakterle (genellikle bir soru işareti) değiştirmek. Bu davranışı, kodlamasını doğru şekilde belirtmemiş bazı web sayfalarında fark etmiş olabilirsiniz. Hatalar argümanı için “replace” değeri, tam olarak bunu yapıyor.
Son olarak “backslashreplace” değeri, her bozuk karakteri Python’ın ters eğik çizgi (\) kullanan kaçış dizileriyle değiştirir. Bu yöntem, sorunun kök nedenini ayıklamanıza yardımcı olabileceğinden test aşamalarında veya bir geliştirici araçları paketinin parçası olarak kullanışlı olabilir.
Kaynak: www.howtogeek.com