大きなテキスト ファイル (~232GB) からいくつかのキーワードを検索しようとしています。速度を考慮してバッファリングを利用し、それらのキーワードを含む行の開始位置を記録したいと考えています。
ここで、同様の質問について議論している多くの投稿を見てきました。ただし、バッファリング (イテレータとしてファイルを使用) を使用するソリューションは、正しいファイル位置を与えることができず、これらのソリューションは通常f.readline()
、バッファリングを使用しない を使用するだけで正しいファイル位置を与えることができます。
両方を実行できる唯一の答えは次のとおり です。
# Read in the file once and build a list of line offsets
line_offset = []
offset = 0
for line in file:
line_offset.append(offset)
offset += len(line)
file.seek(0)
# Now, to skip to line n (with the first line being line 0), just do
file.seek(line_offset[n])
ただし、offset += len(line)
操作に無駄な時間がかかるかどうかはわかりません。これを行うより直接的な方法はありますか?
アップデート:
私はいくつかのタイミングを取りましたが、.readline()
ファイルオブジェクトをイテレータとして使用するよりもはるかに遅いようですpython 2.7.3
. 次のコードを使用しました
#!/usr/bin/python
from timeit import timeit
MAX_LINES = 10000000
# use file object as iterator
def read_iter():
with open('tweets.txt','r') as f:
lino = 0
for line in f:
lino+=1
if lino == MAX_LINES:
break
# use .readline()
def read_readline():
with open('tweets.txt', 'r') as f:
lino = 0
for line in iter(f.readline,''):
lino+=1
if lino == MAX_LINES:
break
# use offset+=len(line) to simulate f.tell() under binary mode
def read_iter_tell():
offset = 0
with open('tweets.txt','rb') as f:
lino = 0
for line in f:
lino+=1
offset+=len(line)
if lino == MAX_LINES:
break
# use f.tell() with .readline()
def read_readline_tell():
with open('tweets.txt', 'rb') as f:
lino = 0
for line in iter(f.readline,''):
lino+=1
offset = f.tell()
if lino == MAX_LINES:
break
print ("iter: %f"%timeit("read_iter()",number=1,setup="from __main__ import read_iter"))
print ("readline: %f"%timeit("read_readline()",number=1,setup="from __main__ import read_readline"))
print ("iter_tell: %f"%timeit("read_iter_tell()",number=1,setup="from __main__ import read_iter_tell"))
print ("readline_tell: %f"%timeit("read_readline_tell()",number=1,setup="from __main__ import read_readline_tell"))
結果は次のようになります。
iter: 5.079951
readline: 37.333189
iter_tell: 5.775822
readline_tell: 38.629598