web-dev-qa-db-ja.com

開いているファイルでread()を2回呼び出せないのはなぜですか?

私がやっている演習では、read()メソッドを使用して、指定されたファイルの内容を2回読み取ろうとしています。奇妙なことに、2回目に呼び出したときに、ファイルの内容が文字列として返されないようです。

ここにコードがあります

_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
_

もちろん、これは最も効率的でも最良の方法でもないことを知っています。これはここのポイントではありません。ポイントは、なぜread()を2回呼び出せないのですか?ファイルハンドルをリセットする必要がありますか?またはそれを行うためにファイルを閉じ/再度開きますか?

85
helpermethod

read()を呼び出すと、ファイル全体を読み取り、ファイルの最後に読み取りカーソルを残します(これ以上読み取るものはありません)。一度に特定の行数を読みたい場合は、readline()readlines()を使用するか、_for line in handle:_を使用して行を繰り返します。

質問に直接答えるには、ファイルが読み取られたら、read()seek(0)を使用して、ファイルの先頭に読み取りカーソルを戻すことができます(ドキュメントは こちら )。ファイルが大きすぎないことがわかっている場合は、findall式で使用して、read()出力を変数に保存することもできます。

追伸ファイルを使い終わったら、忘れずにファイルを閉じてください;)

135
Tim

ええ、上記のように...

例を挙げます。

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

これまでにこの質問に答えた人は誰でも絶対に正しいです-read()はファイル内を移動するため、呼び出した後は再度呼び出すことはできません。

私が追加するのは、あなたの特定のケースでは、最初に戻ってファイルを開いたり、開いたりする必要はなく、読んだテキストをローカル変数に保存して、2回使用することです、またはあなたのプログラムで好きなだけ:

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
16
Tom Anderson

読み取りポインタは、最後の読み取りバイト/文字の後に移動します。 seek()メソッドを使用して、読み取りポインタを先頭に巻き戻します。

開いているすべてのファイルには、関連付けられた位置があります。
read()をすると、その位置から読みます。たとえば、read(10)は新しく開いたファイルから最初の10バイトを読み取り、次に別のread(10)は次の10バイトを読み取ります。引数なしのread()は、ファイルの内容をすべて読み取り、ファイルの位置をファイルの最後に残します。次回read()を呼び出すとき、読むものは何もありません。

seekを使用して、ファイルの位置を移動できます。または、おそらくあなたの場合は、1つのread()を実行して、両方の検索の結果を保持することをお勧めします。

2
Douglas Leeder

私はいつも、暗黒の路地を歩くような読み取り方法を見つけます。少し下がって停止しますが、歩数を数えていなければ、自分がどれだけ進んでいるかはわかりません。 Seekは再配置によって解決策を提供します。他のオプションは、ファイルに沿った位置を返すT​​ellです。 Python file apiは、readとfromをread_from(position、bytes)に組み合わせて、より簡単にすることができます-それまでは、このページを読む必要があります

1
whatnick

read() 消費する。したがって、resetファイル、またはseekを再読み込みする前に開始できます。または、タスクに適している場合は、read(n)を使用してnバイトのみを消費できます。

1
towi