Açık bir dosyada neden iki kez read () çağıramıyorum?


100

Yaptığım bir alıştırma için, belirli bir dosyanın içeriğini read()yöntemi kullanarak iki kez okumaya çalışıyorum . Garip bir şekilde, onu ikinci kez çağırdığımda, dosya içeriğini bir dizge olarak döndürmüyor gibi görünüyor?

İşte kod

f = f.open()

# get the year
match = re.search(r'Popularity in (\d+)', f.read())

if match:
  print match.group(1)

# get all the names
matches = re.findall(r'<td>(\d+)</td><td>(\w+)</td><td>(\w+)</td>', f.read())

if matches:
  # matches is always None

Tabii ki bunun en verimli veya en iyi yol olmadığını biliyorum, buradaki mesele bu değil. Mesele şu ki, neden read()iki kez arayamıyorum? Dosya tutamacını sıfırlamam gerekiyor mu? Veya bunu yapmak için dosyayı kapatıp / yeniden açın?


2
Okumanın dosyanın durumunu değiştirmeyeceği fikrini nereden edindiniz? Hangi referans veya öğreticiyi kullanıyorsunuz?
S. Lot

Dosyayı kapatıp yeniden açmanın aşağıdaki yanıtlara göre çalışması gerektiğine inanıyorum.
Anthony

1
@Shynthriir: Dosyayı kapatmak ve yeniden açmak her zaman iyi bir fikir değildir çünkü sistemde başka etkileri olabilir (geçici dosyalar, incron, vb.).
Ignacio Vazquez-Abrams

3
Sadece bariz olanı belirtmek istiyorum: Read () 'ı iki kez çağırdınız !

4
W / R / T / S. Lot ve 5 yıldan sonra: Bunun gerçekten python belgelerinde olması gerekiyor. Bir ... bir iletmenin veri / fonksiyonel tarzı programlarla çalışmaktadır için kullanılır, özellikle eğer bir dosya nesnesi okuma şey durumunu değiştirecek varsayalım gerektiği açık değildir
Paul Gowder

Yanıtlar:


159

Arama read(), tüm dosyayı okur ve okuma imlecini dosyanın sonunda bırakır (okunacak başka bir şey kalmaz). Bir kerede hatları belirli sayıda okumak isteyen varsa kullanabilirsiniz readline(), readlines()ya yinelerler üzerindeki hatlar üzerinden for line in handle:.

Sorunuzu doğrudan yanıtlamak için, bir dosya okunduktan sonra, ile okuma imlecini dosyanın başlangıcına döndürmek için read()kullanabilirsiniz seek(0)(belgeler burada ). Dosyanın çok büyük olmayacağını biliyorsanız, read()çıktıyı findall ifadelerinizde kullanarak bir değişkene de kaydedebilirsiniz .

Ps. İşiniz bittikten sonra dosyayı kapatmayı unutmayın;)


4
+1, Evet, gereksiz dosya giriş / çıkışlarını önlemek için lütfen geçici değişkeni okuyun. Daha az (açık) değişkene sahip olduğunuz için herhangi bir hafızayı kaydetmeniz yanlış bir ekonomidir.
Nick T

2
@NickT: Birden çok kez okunan küçük bir dosyanın işletim sistemi tarafından önbelleğe alınmasını beklerdim (en azından Linux / OSX'te), bu nedenle iki kez okumak için fazladan dosya G / Ç'si yok. Belleğe sığmayan büyük dosyalar önbelleğe alınmaz, ancak değiştirmeye başlayacağınız için onları bir değişkene okumak istemezsiniz. Bu nedenle, şüphe durumunda, her zaman birkaç kez okuyun. Dosyaların küçük olduğundan eminseniz, en güzel programı veren her şeyi yapın.
Claude

3
Yırtma ile otomatik hale getirilebilir with.
Cees Timmerman

30

evet, yukarıdaki gibi ...

sadece bir örnek yazacağım:

>>> a = open('file.txt')
>>> a.read()
#output
>>> a.seek(0)
>>> a.read()
#same output

18

Şimdiye kadar bu soruyu yanıtlayan herkes kesinlikle haklıdır - read()dosya içinde hareket eder, bu yüzden onu aradıktan sonra tekrar arayamazsınız.

Ekleyeceğim şey, sizin özel durumunuzda, dosyanın başlangıcına geri dönmenize veya dosyayı yeniden açmanıza gerek olmadığıdır, okuduğunuz metni yerel bir değişkende saklayabilir ve iki kez kullanabilirsiniz veya programınızda istediğiniz kadar:

f = f.open()
text = f.read() # read the file into a local variable
# get the year
match = re.search(r'Popularity in (\d+)', text)
if match:
  print match.group(1)
# get all the names
matches = re.findall(r'<td>(\d+)</td><td>(\w+)</td><td>(\w+)</td>', text)
if matches:
  # matches will now not always be None

1
+1 Aslında bu, bu alıştırma için önerilen çözümdü ( code.google.com/intl/de-DE/edu/languages/google-python-class/… ). Ama bir şekilde dizeyi bir değişkende saklamayı düşünmedim. D'oh!
helpermethod

1
Python3 ile pathlib kullanın. from pathlib import Path; text = Path(filename).read_text()Açma, kapama vb.
İşler

14

Okuma işaretçisi, son okunan bayt / karakterden sonra hareket eder. seek()Okuma işaretçisini başa sarmak için yöntemi kullanın .


2

Her açık dosyanın ilişkili bir konumu vardır.
() Okuduğunuzda o pozisyondan okursunuz. Örneğin read(10), yeni açılan bir dosyadan ilk 10 baytı read(10)okur , ardından bir başkası sonraki 10 baytı okur. read()bağımsız değişkenler olmadan dosyanın tüm içeriğini okur ve dosya konumunu dosyanın sonunda bırakır. Bir dahaki sefere aradığında read()okuyacak bir şey yok.

seekDosya konumunu taşımak için kullanabilirsiniz . Ya da muhtemelen sizin durumunuzda daha iyisi, birini yapmak read()ve sonucu her iki arama için de tutmak olacaktır .


1

read() tüketir . Yani, olabilir sıfırlamak dosyası veya aramak yeniden okumadan önce başlamasından. Veya görevinize uyuyorsa, read(n)yalnızca nbayt tüketmek için kullanabilirsiniz .


1

Okuma yöntemini her zaman karanlık bir sokakta yürümek gibi bir şey bulurum. Biraz aşağı inip duruyorsunuz ama adımlarınızı saymıyorsanız, ne kadar ilerlediğinizden emin değilsiniz. Seek, çözümü yeniden konumlandırarak verir, diğer seçenek ise dosya boyunca konumu döndüren Tell'dir. Python dosyası api okuma ve aramayı bir read_from (konum, bayt) olarak birleştirerek daha basit hale getirebilir - bu olana kadar bu sayfayı okumalısınız .

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.