web-dev-qa-db-ja.com

マップされたファイルから行を読み取る方法は?

Mmapインターフェースはreadline()のみをサポートしているようです。オブジェクトを反復処理しようとすると、完全な行ではなく文字が表示されます。

Mmapされたファイルを1行ずつ読み取る「Pythonic」メソッドは何でしょうか。

import sys
import mmap
import os


if (len(sys.argv) > 1):
  STAT_FILE=sys.argv[1]
  print STAT_FILE
else:
  print "Need to know <statistics file name path>"
  sys.exit(1)


with open(STAT_FILE, "r") as f:
  map = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)
  for line in map:
    print line # RETURNS single characters instead of whole line
21
Maxim Veksler

mmapの行を反復処理する最も簡潔な方法は、次のとおりです。

_with open(STAT_FILE, "r+b") as f:
    map_file = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)
    for line in iter(map_file.readline, b""):
        # whatever
_

Python 3では、iter()のセンチネルパラメータはbytes型である必要がありますが、Python 2 it strである必要があります(つまり、_""_ではなく_b""_)。

31
Sven Marnach

私はあなたの例を次のように修正しました:

with open(STAT_FILE, "r+b") as f:
        m=mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)
        while True:
                line=m.readline()
                if line == '': break
                print line.rstrip()

提案:

お役に立てれば。

編集:コメントに興味を持ったので、Linuxでいくつかのタイミングテストを行いました。これは、137MBのテキストファイルでの5回の連続実行で行われたタイミングの比較です。

通常のファイルアクセス:

real    2.410 2.414 2.428 2.478 2.490
sys     0.052 0.052 0.064 0.080 0.152
user    2.232 2.276 2.292 2.304 2.320

mmapファイルアクセス:

real    1.885 1.899 1.925 1.940 1.954
sys     0.088 0.108 0.108 0.116 0.120
user    1.696 1.732 1.736 1.744 1.752

これらのタイミングには、printステートメントは含まれていません(私はそれを除外しました)。これらの数値に従うと、メモリマップトファイルへのアクセスはかなり高速になると思います。

編集2:python -m cProfile test.pyを使用すると、次の結果が得られました。

5432833    2.273    0.000    2.273    0.000 {method 'readline' of 'file' objects}
5432833    1.451    0.000    1.451    0.000 {method 'readline' of 'mmap.mmap' objects}

私が間違っていなければ、mmapはかなり高速です。

さらに、not len(line)のパフォーマンスはline == ''よりも悪いようですが、少なくともそれがプロファイラー出力の解釈方法です。

15
hochl

以下はかなり簡潔です。

_with open(STAT_FILE, "r") as f:
    m = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)
    while True:
        line = m.readline()  
        if line == "": break
        print line
    m.close()
_

lineは改行を保持するため、削除することをお勧めします。これは、_if line == ""_が正しいことを行う理由でもあります(空の行は_"\n"_として返されます)。

元の反復がそのように機能する理由は、mmapがファイルと文字列の両方のように見えようとするためです。反復の目的では、文字列のように見えます。

なぜreadlines()/xreadlines()を提供できない(または提供しないことを選択した)のかわかりません。

1
NPE

Windows上のPython2.7 32ビットは2倍以上の速度マップトファイルでは:

27MB、509k行のテキストファイル(私の「解析」関数は面白くありません。ほとんどの場合、readline()は非常に高速です):

with open(someFile,"r") as f:
    if usemmap:
        m=mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
    else:
        m=f
        e.parse(m)

MMAPの場合:

read in 0.308000087738

MMAPなし:

read in 0.680999994278
0
Richard Aplin