Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonのmmapモジュールでメモリマップトファイルを読み書き・検索する方法

Pythonプログラムでファイルオブジェクトを読み込み、その内容を変更したい場合、アプローチは大きく2つあります。1つ目は、ファイルが存在する物理ストレージ上のデータを直接変更する方法。2つ目は、システムのメモリ(RAM)上でデータを直接変更する方法です。

本記事では、Pythonに標準搭載されているmmapモジュールを使って、ファイルオブジェクトの読み込み・検索・編集を行う方法を解説します。openreadlseekといったシステムコールを何度も呼び出してファイルを操作する代わりに、メモリマッピングではファイルのデータをそのままメモリに配置できるため、メモリ上で直接ファイルを操作できます。

メモリマップトファイルの読み込み

以下の例では、ファイル全体を一度にメモリへ読み込み、ファイルオブジェクトとしてメモリ上に保持します。その後、読み取りモードでアクセスし、ファイル全体を1つのオブジェクトとして扱います。スライスを使って任意の位置から必要なテキストを取り出せる点が特徴です。

サンプルコード

import mmap

def read_mmap(fname):
    with open(fname, mode="r", encoding="utf8") as fobj:
        with mmap.mmap(fobj.fileno(), length=0, access=mmap.ACCESS_READ) as mmap_obj:
            print(mmap_obj[4:26])

read_mmap('E:\\test.txt')

実行結果

上記のコードを実行すると、次のような結果が得られます。

'emissions from gaseous'

mmapを使った高速な文字列検索

mmapは単なる読み書きだけでなく、大容量ファイル内の文字列検索でも威力を発揮します。通常のファイル読み込みと比較することで、そのパフォーマンス差を確認してみましょう。

サンプルコード

import mmap
import time

def regular_io_find(fname):
    with open(fname, mode="r", encoding="utf-8") as fobj:
        text = fobj.read()
        text.find("Death ")

def mmap_io_find(fname):
    with open(fname, mode="r", encoding="utf-8") as fobj:
        with mmap.mmap(fobj.fileno(), length=0, access=mmap.ACCESS_READ) as mmap_obj:
            mmap_obj.find(b"Death ")

start_time_r = time.time()
regular_io_find('E:\\emissions.txt')
end_time_r = time.time()
print("Regular read start time :", start_time_r)
print("Regular read end time :", end_time_r)
print('Regular read time to find: {0}'.format(end_time_r - start_time_r))

start_time_m = time.time()
mmap_io_find('E:\\emissions.txt')
end_time_m = time.time()
print("mmap read start time :", start_time_m)
print("mmap read end time :", end_time_m)
print('mmap read time to find : {0}'.format(end_time_m - start_time_m))

実行結果

上記のコードを実行すると、次のような結果が得られます。

2013
Regular read start time : 1609812463.2718163
Regular read end time : 1609812463.2783241
Regular read time to find: 0.00650787353515625
mmap read start time : 1609812463.2783241
mmap read end time : 1609812463.2783241
mmap read time to find : 0.0

このように、通常の読み込み方式では約0.0065秒かかった検索が、mmapを使うことでほぼゼロの時間で完了しています。これは、ファイル全体を明示的に読み込む必要がなく、OSが管理する仮想メモリ上のページに直接アクセスできるためです。

メモリマップトファイルへの書き込み

次に、ファイルへの書き込み方法を見ていきましょう。以下の例では、アクセスモードとしてr+を指定してファイルを開き、mmapモジュールで読み取りと書き込みの両方を可能にしています。ファイルオブジェクトを作成した後、スライスで書き込み位置を指定し、そこへ文字列を書き込みます。

サンプルコード

import mmap

def mmap_io_write(fname):
    with open(fname, mode="r+") as fobj:
        with mmap.mmap(fobj.fileno(), length=0, access=mmap.ACCESS_WRITE) as mmap_obj:
            mmap_obj[20:26] = b"Hello!"
            mmap_obj.flush()

mmap_io_write('E:\\emissions.txt')

上記のコードを実行後にファイルを開くと、バイト位置20から26にかけて文字列「Hello!」が書き込まれていることを確認できます。

まとめ

mmapモジュールを使うことで、以下のようなメリットが得られます。

  • 高速なアクセス: システムコールのオーバーヘッドを減らし、メモリ上で直接データを操作できる
  • 効率的な検索: find()メソッドにより、大容量ファイル内の文字列検索を高速化できる
  • 部分書き換え: スライスで位置を指定し、ファイルの特定箇所だけを効率よく更新できる

なお、書き込み後はflush()を呼び出して変更をディスクに反映させることを忘れないようにしましょう。また、WindowsとUnix系OSでは挙動に若干の違いがあるため、クロスプラットフォームで利用する場合は注意が必要です。

  1. Pythonのファイルオブジェクトとは?open関数によるファイル操作の基本を徹底解説

    Pythonでは、ファイルを読み書きする際に特別なライブラリをインポートする必要はありません。ファイル操作は言語にネイティブに組み込まれているためです。 まず最初に行うのは、組み込み関数 open() を使ってファイルオブジェクトを取得することです。open() 関数はファイルを開き、ファイルオブジェクトを返します。このファイルオブジェクトには、開いたファイルから情報を取得したり、内容を操作したりするためのメソッドや属性が含まれています。 ファイルとは何か? ファイル操作を行う前に、「ファイルとは何か」を理解しておきましょう。ファイルとは、関連する情報を保存するためにディスク上に確保された「名

  2. PythonのopenpyxlモジュールでExcelファイルを読み書きする方法【初心者向け完全ガイド】

    Pythonには、Excelファイル(.xlsx)を操作するためのopenpyxlという便利なモジュールが用意されています。このモジュールを使えば、Excelファイルの新規作成、データの書き込み・読み取り、シートの追加や管理など、さまざまな操作をプログラムから自動的に行うことができます。 本記事では、openpyxlの基本的な使い方を、実際に動作するサンプルコードとともに順番に解説していきます。 openpyxlのインストール方法 openpyxlは標準ライブラリではないため、まずインストールが必要です。コマンドプロンプト(またはターミナル)で以下のコマンドを実行してください。 pip ins