[編集: この問題は 32 ビット システムにのみ適用されます。お使いのコンピューター、OS、および Python の実装が 64 ビットの場合、巨大なファイルの mmap は確実に機能し、非常に効率的です。]
ファイルへのビット単位の読み取りアクセスを可能にするモジュールを作成しています。ファイルが大きくなる可能性があるため (数百 GB)、ファイルを文字列のように扱い、すべてのシークと読み取りを非表示にする単純なクラスを作成しました。
ラッパー クラスを書いた時点では、mmap モジュールについて知りませんでした。mmap のドキュメントを読んで、「すばらしい。これはまさに私が必要としていたものです。コードを取り出して、mmap に置き換えます。おそらくはるかに効率的であり、コードを削除することは常に良いことです。」
問題は、mmap が大きなファイルに対して機能しないことです! おそらく最も明白なアプリケーションだと思っていたので、これは私にとって非常に驚くべきことです。ファイルが数ギガバイトを超える場合、EnvironmentError: [Errno 12] Cannot allocate memory
. これは 32 ビットの Python ビルドでのみ発生するため、アドレス空間が不足しているように見えますが、これに関するドキュメントは見つかりません。
私のコードはただ
f = open('somelargefile', 'rb')
map = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
だから私の質問は、ここで明らかな何かが欠けているのでしょうか? mmap を大きなファイルで移植可能に動作させる方法はありますか、それとも単純なファイル ラッパーに戻す必要がありますか?
更新: Python mmap には POSIX mmap と同じ制限が必要であるという感覚があるようです。ここで私のフラストレーションをよりよく表現するために、mmap の機能のごく一部を備えた単純なクラスを示します。
import os
class Mmap(object):
def __init__(self, f):
"""Initialise with a file object."""
self.source = f
def __getitem__(self, key):
try:
# A slice
self.source.seek(key.start, os.SEEK_SET)
return self.source.read(key.stop - key.start)
except AttributeError:
# single element
self.source.seek(key, os.SEEK_SET)
return self.source.read(1)
これは読み取り専用で、派手なことは何もしませんが、mmap と同じように実行できます。
map2 = Mmap(f)
print map2[0:10]
print map2[10000000000:10000000010]
ただし、ファイルサイズに制限はありません。さほど難しいことはありません。