web-dev-qa-db-ja.com

Python:ファイルのreadline()操作を取り消して、ファイルポインターを元の状態に戻します

File.readline()を使用して読み取り専用モードでテキストファイルのPythonファイルポインター)をブラウズし、特別な行を探します。その行が見つかったら、ファイルを渡しますファイルポインターがそのreadlineのSTARTにあることを期待しているメソッドへのポインター(直後ではありません)

ファイルポインターでfile.readline()操作を本質的に元に戻すにはどうすればよいですか?

32
MikeN

Readlineの前にfile.tell()を呼び出してからfile.seek()を呼び出して巻き戻すことにより、位置を記憶する必要があります。何かのようなもの:

_fp = open('myfile')
last_pos = fp.tell()
line = fp.readline()
while line != '':
  if line == 'SPECIAL':
    fp.seek(last_pos)
    other_function(fp)
    break
  last_pos = fp.tell()
  line = fp.readline()
_

_for line in file_ループ内でfile.seek()を呼び出しても安全かどうか思い出せないので、通常はwhileループを書きます。これを行うには、おそらくもっとPython的な方法があるでしょう。

44
D.Shawley

readlineを呼び出す前にthefile.tell()で行の開始点を記録し、必要であればthefile.seekでその点に戻ります。

>>> with open('bah.txt', 'w') as f:
...   f.writelines('Hello %s\n' % i for i in range(5))
... 
>>> with open('bah.txt') as f:
...   f.readline()
...   x = f.tell()
...   f.readline()
...   f.seek(x)
...   f.readline()
... 
'Hello 0\n'
'Hello 1\n'
'Hello 1\n'
>>> 

ご覧のとおり、seek/tellの「ペア」は「元に戻す」ことです。つまり、readlineによって実行されるファイルポインターの移動です。もちろん、これは実際のシーク可能な(つまりディスク)ファイルでのみ機能し、ソケットなどのmakefileメソッドで構築されたファイルのようなオブジェクトでは機能しません(たとえば)。

11
Alex Martelli

メソッドが単にファイルを反復処理する場合は、itertools.chain適切なイテレータを作成するには:

import itertools

def process(it):
    for line in it:
        print line,

with open(filename,'r') as f:
    for line in f:
        if 'marker' in line:
            it=itertools.chain((line,),f)
            process(it)
            break
4
unutbu
fin = open('myfile')
for l in fin:
    if l == 'myspecialline':
        # Move the pointer back to the beginning of this line
        fin.seek(fin.tell() - len(l))
        break
# now fin points to the start of your special line
1
GWW

最後の行にアクセスしなかったために最後の行がわからない場合は、改行文字が表示されるまで逆読みできます。

with open(logfile, 'r') as f:
    # go to EOF
    f.seek(0, os.SEEK_END)
    nlines = f.tell()
    i=0
    while True:
        f.seek(nlines-i)
        char = f.read(1)
        if char=='\n':
            break
        i+=1
0
JLT