Aşağıdakilerin tercih edilmesinin tam bir nedeni vardır:
with open('filename.txt') as fp:
for line in fp:
print line
Hepimiz çöp toplama için CPython'un nispeten belirleyici referans sayma şeması ile şımarık. Python'un diğer varsayımsal uygulamaları, with
belleği geri kazanmak için başka bir şema kullanırlarsa , blok olmadan dosyayı "yeterince hızlı" kapatmayabilir.
Böyle bir uygulamada, kodunuz dosyaları çöp toplayıcının artık dosya tanıtıcılarında sonlandırıcıları çağırmasından daha hızlı açarsa işletim sisteminden "çok fazla dosya açık" hatası alabilirsiniz. Genel çözüm, GC'yi hemen tetiklemektir, ancak bu kötü bir hack'tir ve kütüphanelerde olanlar da dahil olmak üzere hatayla karşılaşabilecek her işlev tarafından yapılmalıdır . Ne kabustu ama.
Ya da sadece with
bloğu kullanabilirsiniz .
Bonus soru
(Yalnızca sorunun nesnel yönleriyle ilgileniyorsanız şimdi okumayı bırakın.)
Neden dosya nesneleri için yineleyici protokolüne dahil edilmiyor?
Bu API tasarımı hakkında öznel bir soru, bu yüzden iki bölümde öznel bir cevap var.
Bağırsak seviyesinde bu yanlıştır, çünkü yineleyici protokolünün iki ayrı şey yapmasını sağlar - satırlar üzerinde yineleme ve dosya tanıtıcısını kapatma - ve genellikle basit görünümlü bir işlevin iki işlem yapması kötü bir fikirdir. Bu durumda, yineleyiciler bir dosyanın içeriğiyle yarı işlevsel, değer tabanlı bir şekilde ilişkili olduğu için özellikle kötü hissettirir, ancak dosya tanıtıcılarını yönetmek tamamen ayrı bir görevdir. Her ikisini de görünmez bir şekilde tek bir eylemde ezmek, kodu okuyan ve program davranışı hakkında akıl yürütmeyi zorlaştıran insanlar için şaşırtıcıdır.
Diğer diller de aynı sonuca varmıştır. Haskell kısaca, bir dosyanın üzerinde yinelemenizi ve akışın sonuna geldiğinizde otomatik olarak kapanmasını sağlayan "tembel IO" ile flört etti, ancak bu günlerde Haskell'de tembel IO kullanmanın neredeyse evrensel olarak cesareti kırıldı ve Haskell kullanıcılar çoğunlukla with
Python'daki blok gibi davranan Conduit gibi daha açık kaynak yönetimine geçtiler .
Teknik düzeyde, yineleme dosya tanıtıcısını kapattığında da işe yaramayacak bir dosya tanıtıcısıyla yapmak isteyebileceğiniz bazı şeyler vardır. Örneğin, dosyayı iki kez yinelemem gerektiğini varsayalım:
with open('filename.txt') as fp:
for line in fp:
...
fp.seek(0)
for line in fp:
...
Bu daha az yaygın bir kullanım durumu olsa da, başlangıçta ilk üç satırı içeren mevcut bir kod tabanına altta üç kod satırını eklemiş olabileceğimi düşünün. Yineleme dosyayı kapatsaydı, bunu yapamazdım. Bu nedenle, yineleme ve kaynak yönetimini ayrı tutmak, kod parçalarını daha büyük, çalışan bir Python programına dönüştürmeyi kolaylaştırır.
Oluşturulabilirlik, bir dilin veya API'nın en önemli kullanılabilirlik özelliklerinden biridir.