カネキン伊藤テック

Gzip圧縮・伸張の扱い

Pythonでgzipでの圧縮・伸長(展開/解凍)を行うには組み込みライブラリ gzip を利用する。

組み込みライブラリなので特に pip install などで外部のパッケージをインストールしなくても利用できる。

バイト列を圧縮してgzipファイルとして書き込む

write() などを実装するファイルライクなオブジェクトを作成する gzip.GzipFile() でGzipFileオブジェクトを書き込みモードで開き, write() で書き込む。

import gzip

data_to_write = ("本日は晴天なり\n" * 100).encode("utf-8")  # encodeしてバイト列として得る

with gzip.GzipFile("./test.txt.gz", "wb") as fh:
	# wb = 書き込み(w) + バイナリ(b) モード
	fh.write(data_to_write)
	fh.flush()  # Pythonのバージョンによってはgzipの実装バグで必要なことがある

バイト列をgzip圧縮した結果をバイト列で得る

組み込みライブラリ io にある io.BytesIO を使うことでバイト列をgzip圧縮した結果を BytseIO に書き込み、それを得るとよい。

import gzip
import io

# メモリ上にioできるBytesIOオブジェクトを作成
bytes_io = io.BytesIO()

data_to_write = ("本日は晴天なり\n" * 100).encode("utf-8")  # encodeしてバイト列として得る


with gzip.GzipFile(fileobj=bytes_io, mode="wb") as fh:
	fh.write(data_to_write)
	fh.flush()  # Pythonのバージョンによってはgzipの実装バグで必要なことがある

bytes_io.seek(0)

compressed_data = bytes_io.getvalue()  # 圧縮されたバイト列(bytes型)

ファイルを圧縮してgzipファイルとして書き込む

読み込みながらgzip圧縮していくことで巨大なファイルも処理できる。

import gzip

source_f = "./sample.txt"
out_f = "./sample.txt.gz"
buf_size = 1024 * 8  # 一度に読み書きする単位(バイト)

with open(source_f, "rb") as in_fh:
	with gzip.GzipFile(out_f, "wb") as out_fh:
		# 読み込める限り読み込みながらgzip圧縮していく
		buf = in_fh.read(buf_size)
		while buf != b'':
			out_fh.write(buf)
			buf = in_fh.read(buf_size)
		
		out_fh.flush()  # Pythonのバージョンによってはgzipの実装バグで必要なことがある


# 小さいファイルなら一度にメモリに読み込んでしまうやり方もアリ
with open(source_f, "rb") as in_fh:
	# 一度にメモリに読み込む
	data = in_fh.read()

	# 書き込む(gzip圧縮する)
	with gzip.GzipFile(out_f, "wb") as out_fh:
		out_fh.write(data)
		out_fh.flush()  # Pythonのバージョンによってはgzipの実装バグで必要なことがある

gzipファイルを伸張して別のファイルに書き込む

gzip.GzipFile から読み込みながら普通のファイルに書き込んでいくことでgzipファイルを伸張しファイル保存できる。

import gzip

source_f = "./sample.txt.gz"
out_f = "./sample.txt"
buf_size = 1024 * 8  # 一度に読み書きする単位(バイト)

with gzip.GzipFile(source_f, "rb") as in_fh:
	with open(out_f, "wb") as out_fh:
		buf = in_fh.read(buf_size)  # bufは伸張された状態で出てくる
		while buf != b'':
			out_fh.write(buf)  # 普通のファイルに書き込んでいく
			buf = _fh.read(buf_size)	

gzipファイルを伸張した結果をバイト列で得る

gzip.GzipFile から read() で一気に読み込めばバイト列で得ることができる。

import gzip

source_f = "./sample.txt.gz"
with gzip.GzipFile(source_f, "rb") as fh:
	data = fh.read()  # dataに一気に読み込んだ伸張されたバイト列が入っている(bytes型)

参考リンク