Soru Ruby's File.open ve f.close için ihtiyaç


Çoğu programlama dilinde dosyalarla çalışma akışının açık-kullanım-yakın olduğu yaygın bir bilgidir. Yine de Ruby'nin kodları eşleşmeyen File.open çağrılarında birçok kez gördüm ve daha sonra buldum bilginin bu mücevher ruby belgelerinde:

I / O akışları, çöp toplayıcı tarafından talep edildiğinde otomatik olarak kapanır.

darkredandyellow dost irc konuyla ilgilenir:
[17:12] evet, ve ayrıca, dosya tanıtıcılarının sayısı genellikle işletim sistemi tarafından sınırlandırılıyor
[17:29] Mevcut dosya tanımlayıcılarını kolayca tükediğinizi varsayalım önce çöp toplayıcı temizler. Bu durumda, bunları kendiniz kapatmak isteyebilirsiniz. "çöp toplayıcı tarafından iddia edildi." GC'nin gelecekte bir noktada hareket ettiği anlamına gelir. ve pahalı. dosyaları açıkça kapatmak için birçok neden.

  1. Açıkça kapatmamız gerekecek mi?
  2. Eğer evetse o zaman neden GC otomatik olarak kapanıyor?
  3. Değilse o zaman neden seçeneği?

76
2018-01-25 15:38


Menşei


'Ortak bilgin', yıkıcılar icat edildiğinden beri modası geçmişti. - meagar♦
@meager: Yıkıcılar ne zaman icat edildi? - Andrew Grimm
Sadece bir not: Dosya tanımlayıcıları sınırlı olsa da, Linux'ta en azından sınır oldukça yüksektir. - Linuxios
@ Linuxios: ubuntu12.04'ümde $ ulimit -n => 1024 Sadece basit bir iş yaptığınız zaman sadece yüksek. Kötü alışkanlık bir gün büyük sorunlara neden olacak! - HVNSweeting


Cevaplar:


Ruby kodlarında eşsiz bir çok kez gördüm File.open aramalar

Bir örnek verebilir misin? Ben sadece yeni kimler tarafından yazılmış kodda bunu görüyorum eksiklik "çoğu programlama dilinde ortak bilgi, dosyalarla çalışma akışının açık-kullanım-kapanmasıdır".

Tecrübeli Rubyistler ya dosyalarını açıkça kapatırlar ya da daha aptalca blok formunu kullanırlar. File.opendosyayı sizin için otomatik olarak kapatır. Uygulaması temel olarak böyle bir şeye benziyor:

def File.open(*args, &block)
  return open_with_block(*args, &block) if block_given?
  open_without_block(*args)
end

def File.open_without_block(*args)
  # do whatever ...
end

def File.open_with_block(*args)
  yield f = open_without_block(*args)
ensure
  f.close
end

Komut dosyaları özel bir durumdur. Komut dosyaları genellikle çok kısa çalışırlar ve çok az dosya tanıtıcısı kullanırlar, çünkü bunları kapatmak için mantıklı değildir, çünkü işletim sistemi betik çıktığında bunları kapatır.

Açıkça kapatmamız gerekecek mi?

Evet.

Eğer evetse o zaman neden GC otomatik olarak kapanıyor?

Nesneyi topladıktan sonra, dosyayı artık kapatmanın bir yolu yoktur ve bu nedenle dosya tanımlayıcılarını sızdırmazsınız.

Dosyaları kapatan çöp toplayıcı olmadığını unutmayın. Çöp toplayıcı, bir nesne için toplayana kadar herhangi bir sonlandırıcıyı çalıştırır. Sadece öyle oluyor ki File sınıf, dosyayı kapatan bir sonlandırıcı tanımlar.

Değilse o zaman neden seçeneği?

Çünkü boşa harcanan bellek ucuzdur, ancak israf dosyalarının israfı değildir. Bu nedenle, bir dosya tanımlayıcısının ömrünü bir miktar bellek hafızasına bağlamak mantıklı değildir.

Sadece tahmin edemezsin ne zaman çöp toplayıcı çalışır. Tahmin bile edemezsin Eğer o koşacak hiç: Eğer hiç bellek tükenmezse, çöp toplayıcısı asla çalışmaz, bu nedenle finalizer asla çalışmayacaktır, bu nedenle dosya asla kapanmayacaktır.


113
2018-01-25 16:04



github.com/isaac/sunspot/blob/cell/sunspot/lib/sunspot/... +23 (her ne kadar Kernel # temelde HTTP tarafı için açık ve kullanılmış olsa da, buna yerel dosya yolu parametresiyle ulaştım, yine de ...) hala yama ve istek-çekme için zaman bulmaya çalışıyorum), github.com/jnicklas/carrierwave Ctrl + f "File.open" (bir örnek olarak verilmiştir, ancak kötü bir şekilde ...) ve hatırlamıyorum birkaç diğer yerler. Projelerimde istikrar gereklilikleri nedeniyle konuyla ilgili bir kayığım var. - clyfe
Bu örnekte, kurtarma bloğu içinde yer almalı mıdır? Yükseltme çağrılırsa ve istisna olmazsa bu bir çalışma zamanı hatası alamaz mı? - Jeff Storey
@JeffStorey: güzel yakalama! 17 ay fark edilmeden… - Jörg W Mittag
@ JörgWMittag ve şimdi 17 ay daha sabit değil: P Sanırım burada ana nokta ensure, rescue ve raise hiç gerekli değildir. - KL-7
Bence sahip olamazsın ensure olmadan rescue. Ve sadece sessizce istisnayı yutmazsınız, dosyayı kapattıktan sonra onu arayan kişiye iletmeniz gerekir. Neyse, bana yine Mayıs ayında '15 :-D'yi hatırlat - Jörg W Mittag


Kullandıktan sonra dosya tanımlayıcılarını her zaman kapatmalısınız, bu da aynı zamanda temizleyecektir. Çoğu zaman insanlar File.open dosya tanımlayıcı ömrünü işlemek için bloklarla eşdeğer yöntem. Örneğin:

File.open('foo', 'w') do |f|
    f.write "bar"
end

Bu örnekte dosya otomatik olarak kapatılır.


62
2018-01-25 15:47



İyi bir nokta. File.close'u çağırmayan bir betiğe bir hata izledim. Sonuç olarak, şimdi ve sonra bazı dosyalarda son satır eksik olacaktır. - Erwan Legrand
Olağanüstü. Bu hileyi hiç bilmiyordum. Bu konuda çok java-8 gibi. Teşekkür ederim. - sagneta


  1. Evet
  2. Yapmazsanız ya da başka bir başarısızlık varsa
  3. 2'ye bakın.

1
2018-01-25 15:40





Göre http://ruby-doc.org/core-2.1.4/File.html#method-c-open

İlişkili hiçbir blok ile, File.open :: new için bir eşanlamlıdır. Eğer   İsteğe bağlı kod bloğu verilir, açılan dosya bir argüman olarak iletilir.   ve Dosya nesnesi bloktan sonra otomatik olarak kapanacaktır   sonlandırır. Bloğun değeri File.open'den döndürülecektir.

Bu nedenle, blok bittiğinde otomatik olarak kapanacak : D


1
2018-05-26 17:31





Kullanabiliriz File.read() ruby içinde dosyayı okumak için fonksiyon ..... gibi,

file_variable = File.read("index.html")

bu örnekte file_variable o dosyanın tam değerine sahip olabilir.


-1
2018-01-10 12:09