Pythonのmmapの使い方|ファイルのreadやwriteのやり方を解説

スポンサーリンク

PythonのファイルI/Oには多くの方法があり、mmapは最もクールな方法ですが、ほとんど使われていません。

この記事では、Pythonのmmap関数を学び、mmap関数の基本概念であるメモリマッピングについても学びます。

スポンサーリンク

メモリマッピングとは?

メモリマッピングは、マシンレベルの構造を使用して、ディスクからプログラムで使用するためにファイルを直接マッピングするプロセスです。

ディスク内のファイル全体を、コンピュータプログラムのアドレス空間内のアドレス範囲にマッピングします。

プログラムは、ランダムアクセスメモリのデータにアクセスするのと同じ方法で、ディスク上のファイルにアクセスすることができます

コンピュータのメモリ管理

メモリマッピングのプロセスとmmapの動作を明確に理解するために、コンピュータのメモリの種類を簡単に理解することにしましょう。

  • 物理メモリ。ランダムアクセスメモリ(RAM)で、揮発性メモリです。プログラムが動作している間、利用可能です。
  • 仮想メモリ。64ビットのマシンであれば、170億ギガバイトのデータにアクセスすることができる。しかし、実際には、私たちの物理メモリは、パソコンでは最大8ギガバイトまたは16ギガバイトです。コンピュータは物理メモリを仮想空間にマッピングし、より大きなプログラムを実行する場合はスワップ領域と呼ばれるストレージディスクの一部を使用して少ないメモリを補い、たとえファイルのサイズが大きくても気にする必要はありません。使用中にデータをディスクからメモリにスワップするために、異なるページング技術が使用されます。
  • 共有メモリ。ページングや仮想メモリのような技術を使って、たとえ容量が少なくても1つの物理メモリを使用して複数のプログラムを同時に実行することができます。使用しないデータはスワップメモリに送り、使用するデータはメインメモリにコピーすることで、すべてのプログラムが動作します。

mmap機能は、仮想メモリの概念を使って、プログラムからは大きなファイルがメインメモリにロードされたように見える。

しかし、実際にはそのファイルはディスク上にしか存在しません。

オペレーティングシステムは、ファイルのアドレスをプログラムのアドレス空間にマッピングして、プログラムがファイルにアクセスできるようにしているだけです。

Pythonでmmap関数を使うには?

ファイル入出力にmmapモジュールを使うと、単純なファイル入出力に代わ って、ファイル入出力を行うことができます。

以下の例で、mmapの使い方を理解しましょう。

#import module
import mmap
 
#define filepath
filepath="/home/aditya1117/askpython/sample.txt"
 
#create file object using open function call
file_object= open(filepath,mode="r",encoding="utf8")
 
#create an mmap object using mmap function call
mmap_object= mmap.mmap(file_object.fileno(),length=0,access=mmap.ACCESS_READ,offset=0)
 
#read data from mmap object
txt=mmap_object.read()
 
#print the data
print("Data read from file in byte format is:")
print(txt)
print("Text data is:")
print(txt.decode())

結果は以下の通りです。

Data read from file in byte format is:
b'This is a sample file for mmap tutorial.
'
Text data is:
This is a sample file for mmap tutorial.

上の例では

  1. まず、mmap モジュールをインポートします。
    次に、ディスクにファイルのパスを定義します。
    open()システムコールを使って、file_objectを作成します。
    1. ファイルオブジェクトを取得した後、mmap 関数を使用して、プログラムのアドレス空間にファイルのメモリマッピングを作成します。
    1. 次に、mmapオブジェクトからデータを読み込みます。
      そして、そのデータをプリントします。

mmap関数の説明

mmap_object= mmap.mmap(file_object.fileno(),length=0,access=mmap.ACCESS_READ,offset=0)

mmapは最初の引数にファイルディスクリプタを要求します。

引数lengthはマップするメモリのサイズをバイト単位で取り、引数accessはプログラムがメモリにどのようにアクセスするかをカーネルに通知します。

引数offsetは、オフセットで指定された特定のバイト以降にファイルのメモリマップを作成するようプログラム に指示します。

  • 第1引数のファイルディスクリプタは、ファイルオブジェクトの fileno()メソッドで提供されます。
  • 第2引数のlengthには0を指定することで、十分な量のメモリを自動的に選択してファイル・マップを作成します。
  • access引数には多くのオプションがあります。ACCESS_READ は、マップされたメモリーからの読み出しのみを許可します。ACCESS__COPY と ACCESS_WRITE は、書き込みモードのアクセスを提供します。ACCESS_WRITEモードでは、マップされたメモリとファイルの両方を変更することができますが、ACCESS モードでは、マップされたメモリのみが変更されます。
  • 引数offsetは、ファイルを先頭アドレスからマップする場合、0を指定することが多い。

メモリマップドファイルにデータを書き込むには?

メモリマップドファイルにデータを書き込むには、アクセス引数に ACCESS_WRITE オプションを指定し、ファイルを r+ モードでオープンしてファイルオブジェクトを作成した後、 mmap_object.write() 関数でファイルに書き込むことが可能です。

ここで注意しなければならないのは、mmapは空のファイルのマッピングを許さないという点です。

これは、空のファイルは単なるメモリのバッファであるため、メモリマッピングが不要であるという理由によるものです。

もし、wモードでファイルを開くと、mmapはValueErrorを引き起こします。

#import module
import mmap
 
#define filepath
filepath="/home/aditya1117/askpython/sampleoutput.txt"
 
#create file object using open function call
file_object= open(filepath,mode="r+",encoding="utf8")
print("Initial data in the file is:")
print(file_object.read())
 
#create an mmap object using mmap function call
mmap_object= mmap.mmap(file_object.fileno(),length=0,access=mmap.ACCESS_WRITE,offset=0 )
 
#write something into file
text="Aditya is writing this text to file  "
mmap_object.write(bytes(text,encoding="utf8"))
 
# read data from file
nfile_object= open(filepath,mode="r+",encoding="utf8")
 
print("Modified data from file is:")
print(nfile_object.read())

結果は、以下の通りです。

Initial data in the file is:
This is a sample file for mmap tutorial in python.
 
Modified data from file is:
Aditya is writing this text to file  al in python.

上記の例で注意しなければならないのは、mmapに書き込む前に入力をバイトに変換する必要があるということです。

また、mmapはファイルの先頭アドレスからデータを書き始め、初期データを上書きしてしまいます。

もし、以前のデータを保存する必要がある場合は、mmap 関数呼び出しの中で適切なオフセットを指定することで、保存することができます

mmap を使ってファイルの特定の部分にアクセスする方法は?

mmap オブジェクトは Python のリストでスライシングを使うように、スライスすることができます

mmap オブジェクトは文字列の振る舞いを示し、文字列に対して行われる多くの操作を mmap オブジェクトに適用することができます


mmapオブジェクトはPythonのリストでスライシングを使うようにスライスすることができます

例えば、ファイルの10文字目から99文字目までを読みたいとします。

次の例のようにできます。

#import module
import mmap
 
#define filepath
filepath="/home/aditya1117/askpython/sample.txt"
 
#create file object using open function call
file_object= open(filepath,mode="r",encoding="utf8")
 
#create an mmap object using mmap function call
mmap_object= mmap.mmap(file_object.fileno(),length=0,access=mmap.ACCESS_READ,offset=0 )
print("Complete data in byte format is:")
print(mmap_object.read())
print("Data from 9th to 97th character is:")
#print 10th to 99th character
print(mmap_object[9:98])

結果は以下の通りです。

Complete data in byte format is:
b'We can access a part of file directly using mmap objects. mmap objects can be sliced as we use slicing on python lists.mmap objects show the behavior of strings and many operations which are done on strings can be applied to mmap objects.mmap objects can be sliced as we use lists in python. Suppose we want to read from the 10th to 99th character of the file. We can do so as shown in the following example.
'
Data from 9th to 97th character is:
b'cess a part of file directly using mmap objects. mmap objects can be sliced as we use sli'

なぜPythonでmmapを使うのか?

単純な読み書き操作では、実行中に多くのシステムコールが発生し、その過程で異なるバッファに何度もデータがコピーされます。

mmapを使用すると、特に大規模なファイルI/Oが必要なプログラムでは、これらの関数呼び出しやバッファ操作をスキップできるため、パフォーマンスの面で大きな改善が得られます。

まとめ

この記事では、まず、メモリマッピングとは何かを見てきました。

次に、メモリ管理技術について見てきました。

そして、Pythonでmmapを使う方法を様々な例を使って説明し、この関数の動作の背後にあるいくつかの技術的な側面も見てきました。

タイトルとURLをコピーしました