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
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""
_)。
私はあなたの例を次のように修正しました:
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()
提案:
map
を呼び出さないでください。これは組み込み関数です。mmap
ヘルプページのPythonの例のように、r+b
モードでファイルを開きます。次のように記載されています:いずれの場合も、更新用に開いたファイルのファイル記述子を指定する必要があります。 http://docs.python.org/library/mmap.html#mmap.mmapを参照) 。UPPER_CASE_WITH_UNDERSCORES
グローバル変数名は使用しないことをお勧めします。 /#global-variable-names 。他のプログラミング言語(Cなど)では、定数はすべて大文字で記述されることがよくあります。お役に立てれば。
編集:コメントに興味を持ったので、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 == ''
よりも悪いようですが、少なくともそれがプロファイラー出力の解釈方法です。
以下はかなり簡潔です。
_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()
を提供できない(または提供しないことを選択した)のかわかりません。
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