Dosyaları açıkça kapatmak önemli mi?


149

Python'da, bir dosyayı çağırmadan açarsanız close()veya dosyayı kapatır ancak try- finallyveya " with" ifadesini kullanmazsanız, bu bir sorun mudur? Yoksa tüm dosyaları kapatmak için Python çöp koleksiyonuna güvenmek bir kodlama uygulaması mıdır? Örneğin, biri bunu yaparsa:

for line in open("filename"):
    # ... do stuff ...

... bu bir sorun mu var çünkü dosya asla kapatılamıyor ve kapatılmasını önleyen bir istisna oluşabiliyor mu? Yoksa fordosya kapsam dışında olduğu için ifadenin sonunda kesinlikle kapatılacak mı?


13
Dosya yok değil sonunda kapsam dışına çıkar forbloğu. Referans sayısı sıfıra inerek otomatik olarak kapanmasına neden olur, ancak yalnızca bileşikler, sınıflar ve modüller Python'daki kapsamları tanımlar, diğer bileşik ifadeleri değil.
agf

18
Sorun olmadığı sürece sorun değil. İşletim sistemi düzeyinde, komut dosyası çıktığında komut dosyası tarafından açılan dosyalar kapatılacaktır, bu nedenle dosyaları takma aracı komut dosyalarında kapatma konusunda endişelenmenize gerek yoktur. Bununla birlikte, süreçlerin koruyabilecekleri açık dosya sayısı üzerinde bir sınırı vardır, bu nedenle uzun ömürlü veya karmaşık komut dosyalarının daha dikkatli olması gerekebilir. Her durumda, dosyalarınızı kapatmak iyi bir alışkanlıktır.
Russell Borogove

3
@agf: Dosyanın kapsam dışına çıkmadığı konusunda haklısınız, ancak forbloklar ve işlevler / sınıflar / modüller arasındaki ayrımla ilgili değil . Bundan çok daha basit: nesnelerin kapsamı yok, sadece isimler var. Bu nesneyi ifade eden bir isim yoktur, bu yüzden burada kapsamda kalacak veya kapsam dışında kalacak hiçbir şey yoktur.
maksimum

@max Yorumum, fordöngü ile ilişkili bir kapsam olduğu varsayımını düzeltiyor ve dosyanın tamamen farklı bir nedenden dolayı kapatıldığını belirtiyor. Burada alakalı olmadığı için Python'da hangi kapsamların içine girmez .
agf

@max döngü için örtülü bir referans var ... bu bir anlambilim argümanı
Peter R

Yanıtlar:


126

Örneğinizde, yorumlayıcı çıkmadan önce dosyanın kapatılacağı garanti edilmez. CPython'un mevcut sürümlerinde, dosya for döngüsünün sonunda kapatılacaktır çünkü CPython, birincil çöp toplama mekanizması olarak referans sayımını kullanır, ancak bu bir dilin özelliği değil, bir uygulama detayıdır. Python'un diğer uygulamalarının bu şekilde çalışacağı garanti edilmez. Örneğin IronPython, PyPy ve Jython referans sayımı kullanmaz ve bu nedenle döngü sonunda dosyayı kapatmaz.

Kodunuzu daha az taşınabilir kıldığı için CPython'un çöp toplama uygulamasına güvenmek kötü bir uygulamadır. CPython kullanıyorsanız kaynak sızıntısı olmayabilir, ancak referans sayımı kullanmayan bir Python uygulamasına geçerseniz, tüm kodunuzu gözden geçirmeniz ve tüm dosyalarınızın düzgün bir şekilde kapatıldığından emin olmanız gerekir.

Örnek kullanımınız için:

with open("filename") as f:
     for line in f:
        # ... do stuff ...

8
Kullanıldıktan with open() as fsonra dosya otomatik olarak kapatılıyor mu?
Rohan

25
@Rohan evet, bu withifadenin sağladığı küçük sihir , ama elbette bu büyünün çalışması için nesnenin özel yöntemleri olmalı __enter__ve daha __exit__sonra nesnede closeve yapılması gereken diğer temizleme şeyleri withaçıklamasının sonu ...
Copperfield

1
FYI: Bu cevap sadece "ne zaman kapatılacağını" açıklıyor ama "açık kalırsa" açıklamıyor. İkincisi için lütfen "Bir dosya açık kalırsa ne olur?" bu cevabın bir parçası ( askubuntu.com/questions/701491/… )
RayLuo

Ayrıca, dosyaların kapatılmaması dosyaların kapatılmamasına neden olabilir.
Erwan Legrand

Dosyayı kapatmazsam, programın çalışması durduktan sonra belleğimi kesin olarak alır mıyım? Yoksa tüm tercümandan çıkmak zorunda mıyım?
Pro Q

22

Bazı Python'lar artık başvuruda bulunulmadığında dosyaları otomatik olarak kapatır, diğerleri ise Python yorumlayıcısı çıktığında dosyaları kapatmak O / S'ye bağlıdır.

Dosyaları sizin için kapatacak Python'lar için bile, zamanlama garanti edilmez: hemen olabilir veya saniye / dakika / saat / gün sonra olabilir.

Bu nedenle, kullandığınız Python ile ilgili sorunlar yaşamasanız da, dosyalarınızı açık bırakmak kesinlikle iyi bir uygulama değildir. Aslında, cpython 3'te, eğer yapmadıysanız, sistemin sizin için dosyaları kapatmak zorunda olduğu konusunda uyarılar alacaksınız.

Ahlak: Kendinizi temizleyin. :)


9
CPython'da artık referans alınmadığında dosyalar kapatılır, ancak bu bir dil özelliği değildir. Eğer öyleyse, oldukça mutlu bir şekilde ona güvenebilirsiniz.
Peter Graham

9

Bu tür bir yapıyı bu özel durumda kullanmak oldukça güvenli olmasına rağmen, bu tür uygulamaları genelleştirmek için bazı uyarılar vardır:

  • run, dosya tanımlayıcılarının tükenmesine neden olabilir, ancak olası olmasa da, böyle bir hata
  • söz konusu dosyayı bazı sistemlerde silemeyebilirsiniz, örn. win32
  • CPython dışında bir şey çalıştırırsanız, dosyanın sizin için ne zaman kapatıldığını bilmezsiniz
  • dosyayı yazma veya okuma-yazma modunda açarsanız, verilerin ne zaman temizleneceğini bilmezsiniz

3

Dosya çöpleri toplar ve böylece kapatılır. GC, ne zaman kapatılacağını belirler, siz değil. Açıkçası, bu önerilen bir uygulama değildir, çünkü dosyaları kullanmayı bitirir bitirmez dosyaları kapatmazsanız açık dosya tanıtıcı sınırına ulaşabilirsiniz. Ya bu fordöngü içinde daha fazla dosya açar ve onları kalırsa?


Ancak, bunun için döngü içinde başka dosyalar açarsanız, herhangi birini açıkça kapatsanız da kapatmasanız da aynı anda birden fazla dosya açık olacaktır. Dosya kapsam dışına çıkar çıkmaz dosyanın mutlaka toplanmayacağını mı söylüyorsunuz, bu nedenle açıkça yapılırsa daha erken kapatılacak mı? Bir istisna meydana geldiğinde ne olur (/ try-finally ile kullandığınızda, bunu yapmıyorsanız)?
user553702

1
CPython'da, referans sayımı forifadeden sonra toplanmasına neden olur - bir sonraki çöp toplama çalışmasını beklemek zorunda kalmazsınız.
agf

3

Merhaba Aynı python betiğinde içeriğini kullanacağınız zaman dosya tanımlayıcınızı kapatmak çok önemlidir. Bugün bu kadar uzun bir hata ayıklama sonra fark ediyorum. Bunun nedeni, yalnızca dosya tanımlayıcıyı kapattıktan ve değişikliklerin dosyadan etkilendikten sonra içeriğin düzenlenmesi / kaldırılması / kaydedilmesidir!

Yani yeni bir dosyaya içerik yazma durumunuz olduğunu varsayalım ve sonra fd'yi kapatmadan bu dosyayı (fd değil) içeriğini okuyan başka bir kabuk komutunda kullanıyorsunuz. Bu durumda, kabuk komutu için beklendiği gibi içerik almazsınız ve hata ayıklamaya çalışırsanız, hatayı kolayca bulamazsınız. blog girişimde daha fazla bilgi edinebilirsiniz http://magnificentzps.blogspot.in/2014/04/importance-of-closing-file-descriptor.html


1

G / Ç işlemi sırasında veriler arabelleğe alınır: bu, dosyaya yazılmadan önce geçici bir yerde tutulduğu anlamına gelir.

Python, yazmayı bitirdiğinizden emin oluncaya kadar arabelleği (yani dosyaya veri) temizlemez. Bunu yapmanın bir yolu dosyayı kapatmaktır.

Kapatmadan bir dosyaya yazarsanız, veriler dosyayı hedef dosyaya yapmaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.