Pythonのlzmaモジュールで学ぶLZMAアルゴリズムによるデータ圧縮
LZMAアルゴリズムとは
LZMA(Lempel–Ziv–Markov chain Algorithm)は、辞書式圧縮方式を採用した可逆(ロスレス)データ圧縮アルゴリズムで、他の圧縮アルゴリズムと比べて非常に高い圧縮率を実現できることで知られています。Pythonの標準ライブラリであるlzmaモジュールには、LZMAアルゴリズムによるデータの圧縮・展開(解凍)を行うためのクラスや便利な関数がまとめられています。
このモジュールが提供する機能はbz2モジュールとよく似ていますが、BZ2Fileクラスと異なり、LZMAFileクラスはスレッドセーフではない点に注意が必要です。
lzma形式で圧縮されたファイルを扱う最も簡単な方法は、lzma.open()関数を使ってファイルオブジェクトを開くことです。
open()
この関数はLZMA形式で圧縮されたファイルを開き、ファイルオブジェクトを返します。主な引数は「ファイル名」と「モード」の2つです。mode引数のデフォルト値は「rb」ですが、以下のいずれかの値を指定できます。
バイナリモード: "r"、"rb"、"w"、"wb"、"x"、"xb"、"a"、"ab" テキストモード: "rt"、"wt"、"xt"、"at"
compress()
この関数は、指定されたデータをLZMAアルゴリズムで圧縮し、バイトオブジェクトとして返します。オプションのformat引数を指定すると、コンテナ形式を選択できます。指定できる値はFORMAT_XZ(デフォルト)とFORMAT_ALONEです。
decompress()
この関数は、圧縮されたデータを展開し、元の非圧縮バイトオブジェクトを返します。
以下の例では、これらの関数を使ってLZMA圧縮データをファイルに書き込んでいます。
>>> import lzma
>>> data = b"Welcome to TutorialsPoint"
>>> f = lzma.open("test.xz","wb")
>>> f.write(data)
>>> f.close()このコードを実行すると、カレントディレクトリに「test.xz」ファイルが作成されます。このファイルから元のデータを読み出すには、次のようにします。
>>> import lzma
>>> f = lzma.open("test.xz","rb")
>>> data = f.read()
>>> data
b'Welcome to TutorialsPoint'lzmaモジュールのオブジェクト指向APIを使って圧縮・展開を行いたい場合は、LZMAFileクラスを使用します。
LZMAFile()
これはLZMAFileクラスのコンストラクタです。ファイルとモードを指定する必要があります。modeに「w」または「wb」を指定して生成したオブジェクトでは、write()メソッドが利用可能になります。
write()
このメソッドは、与えられたデータを圧縮し、その背後にあるファイルへ書き込みます。
>>> data = b'Welcome to TutorialsPoint'
>>> obj = lzma.LZMAFile("test.xz", mode="wb")
>>> obj.write(data)
>>> obj.close()圧縮されたファイルは、mode='rb'を指定して作成したLZMAFileオブジェクトのread()メソッドによって読み込み、展開されたデータを取得できます。
read()
このメソッドは、圧縮ファイルからデータを読み込み、展開済みのデータを返します。
>>> obj = lzma.LZMAFile("test.xz", mode="rb")
>>> data = obj.read()
>>> data
b'Welcome to TutorialsPoint'LZMAアルゴリズムでは、すでに開かれている通常のファイルオブジェクトに対して圧縮データを書き込むことも可能です。次の例では、「test.txt」を組み込みのopen()関数で「wb」モードにより開き、まずテキストを書き込みます。その後、同じファイルを使って圧縮データを書き込んでいます。
>>> f = open("test.txt","wb")
>>> f.write(b"Hello world")
>>> fp = lzma.open(f,"wb")
>>> fp.write(b"Welcome to Python")
>>> f.write(b"Thank you")
>>> f.close()
>>> fp.flush()
>>> fp.close()上記のコードを実行すると、カレントディレクトリに「test.txt」が作成され、圧縮データと非圧縮データが混在した内容になります。
Hello worldý7zXZ æÖ´F!t/å£Thank you
bz2モジュールと同様に、lzmaモジュールにもインクリメンタル(逐次)圧縮・展開のためのクラスが用意されています。
LZMACompressor()
これはインクリメンタルコンプレッサ(逐次圧縮器)オブジェクトを返すコンストラクタです。複数のデータチャンクを個別に圧縮し、それらを連結したデータをファイルに書き込むことができます。
compress()
このメソッドは、与えられたデータを圧縮し、バイトオブジェクトを返します。
flush()
このメソッドはバッファを空にし、残りのデータをバイトオブジェクトとして返します。
次の例では、インクリメンタルコンプレッサオブジェクトを使って、リスト内の各要素を順番に圧縮しています。
>>> data = [b'Hello World', b'How are you?', b'welcome to Python'] >>> obj = lzma.LZMACompressor() >>> bindata = [] >>> for i in data: bindata.append(obj.compress(i)) >>> bindata.append(obj.flush()) >>> bindata [b'\xfd7zXZ\x00\x00\x04\xe6\xd6\xb4F\x02\x00!\x01\x16\x00\x00\x00t/\xe5\xa3', b'', b'', b"\x01\x00'Hello WorldHow are you?welcome to Python\x00\xf5\xc6\xc1d|\xf3\x8ey\x00\x01@(\xd4RJ\xe5\x1f\xb6\xf3}\x01\x00\x00\x00\x00\x04YZ"]
上記のコードでは、元のリストの各要素を圧縮したバイト表現のリストとしてbindataが構築されます。このデータをLZMADecompressorオブジェクトで展開して元のデータを取得するには、次のようにします。
>>> obj = lzma.LZMADecompressor() >>> binstr = b''.join(bindata) >>> obj.decompress(binstr) b'Hello WorldHow are you?welcome to Python'
本記事では、lzmaモジュールに含まれる主要なクラスと関数について、具体例を挙げながら解説しました。高い圧縮率が求められる場面では、ぜひlzmaモジュールを活用してみてください。
-
PythonでMean-Shift(平均シフト)アルゴリズムを実装する方法
機械学習にはさまざまな種類のクラスタリングアルゴリズムが存在し、その多くはPythonで実装できます。本記事では、教師なし学習手法として用いられるクラスタリングアルゴリズムの一つである「Mean-Shift(平均シフト)」について、その仕組みとPythonによる実装方法を解説します。 Mean-Shiftアルゴリズムとは Mean-Shiftアルゴリズムは、データ分布に関する事前の仮定を必要としないノンパラメトリックな手法です。このアルゴリズムでは、各データポイントを反復的に移動させながら、データポイントが最も密集している領域(高密度領域)へとシフトさせることで、クラスタへの割り当てを行いま
-
Pythonのbase64モジュールを使ったデータエンコード・デコード入門
PythonにおけるBase64エンコーディングとはPython標準ライブラリのbase64モジュールは、バイナリデータをプレーンテキスト(ASCII)プロトコルで安全に送信できる形式へ変換するための機能を提供します。メール送信、URLへの埋め込み、HTTP POSTリクエストなど、テキストベースの通信経路でバイナリデータを扱いたい場面で活躍するモジュールです。このモジュールが実装しているのは、RFC 3548で定義されたBase16、Base32、Base64の各アルゴリズム、および事実上の標準となっているAscii85とBase85のエンコーディングです。RFC 3548準拠のエンコーディ