Python の標準ライブラリには tarfile というモジュールがある。 このモジュールを使うと tar 形式で複数のファイルをまとめることができる。 また tarfile モジュールは gzip や bzip2 といった形式の圧縮・展開もサポートしている。 今回は、そんな tarfile モジュールで、利用する場面の多い tar 形式でまとめて gzip 形式で圧縮したファイル (tar.gz) を扱ってみる。
使った環境は次のとおり。
$ sw_vers ProductName: macOS ProductVersion: 13.5 BuildVersion: 22G74 $ python -V Python 3.10.12 $ tar --version bsdtar 3.5.3 - libarchive 3.5.3 zlib/1.2.11 liblzma/5.0.5 bz2lib/1.0.8
もくじ
tar ファイルを展開する
まずは extraction.txt
というテキストファイルが 1 つ入った tar.gz ファイルを用意する。
ファイルは tar(1) コマンドを使って作成して、名前は extraction.tar.gz
にした。
$ echo "Hello, World" > extraction.txt $ tar czvf extraction.tar.gz extraction.txt a extraction.txt $ file extraction.tar.gz extraction.tar.gz: gzip compressed data, last modified: Tue Aug 20 03:03:04 2023, from Unix, original size modulo 2^32 2048
上記のファイルを Python の tarfile モジュールで展開してみる。
以下のサンプルコードでは、アーカイブに含まれるファイルのバイト列を読み取ってファイル名と共に出力している。
tarfile.open()
関数は、モードに "r"
を指定すると自動的に圧縮アルゴリズムを読み取って展開の処理をしてくれる。
"""任意の圧縮方式を使った tar ファイルを展開するサンプルコード""" import tarfile def main(): filepath = "extraction.tar.gz" with tarfile.open(filepath, mode="r") as tar: # アーカイブに含まれるファイルの情報を一覧で取得する members: list[tarfile.TarInfo] = tar.getmembers() for tar_info in members: # ファイル名または TarInfo を指定してファイルオブジェクトにアクセスできる with tar.extractfile(tar_info) as file_fp: # ファイルの内容を出力する print(f"{tar_info.name}: {file_fp.read()}") if __name__ == "__main__": main()
上記を実行してみよう。
$ python extraction.py extraction.txt: b'Hello, World\n'
ちゃんと含まれている extraction.txt
に "Hello, World" という文字列に解釈できるバイト列が含まれることが確認できた。
tar ファイルを作成する
続いては tar ファイルを作成するサンプルコードを示す。
tarfile モジュールの API は、すでにファイルシステムに存在するファイルを扱うものが多い。
しかし、オンメモリのデータをアーカイブにすることも、もちろんできる。
以下では io.BytesIO
を使ってファイルライクオブジェクトを作成し、それをアーカイブに含めている。
アーカイブは compression.tar.gz
という名前で、アーカイブに含まれるファイル名は compression.txt
にした。
なお、gzip 形式で圧縮する場合には tarfile.open()
関数の mode
引数に "w:gz"
を指定する。
"""gzip 形式で圧縮した tar ファイルを作成するサンプルコード""" import tarfile import io def main(): # アーカイブに含めるファイルの内容を用意する file_buffer = io.BytesIO() file_buffer.write("Hello, World\n".encode("ascii")) file_buffer.seek(0) # "w:gz" モードでファイルを開くことで gzip で圧縮した tar ファイルになる filepath = "compression.tar.gz" with tarfile.open(filepath, mode="w:gz") as tar: # アーカイブに含めるファイルの名前を指定する tar_info = tarfile.TarInfo(name="compression.txt") # アーカイブに含めるファイルのサイズを指定する tar_info.size = len(file_buffer.getvalue()) # アーカイブにファイルを追加する tar.addfile(tar_info, fileobj=file_buffer) if __name__ == "__main__": main()
上記を実行してみよう。
$ python compression.py
すると compression.tar.gz
という名前でアーカイブのファイルができる。
$ file compression.tar.gz compression.tar.gz: gzip compressed data, was "compression.tar", last modified: Tue Aug 20 10:50:49 2023, max compression, original size modulo 2^32 10240
tar(1) コマンドを使って展開してみよう。
$ tar zxvf compression.tar.gz x compression.txt
すると compression.txt
というファイルができる。
内容を確認してみよう。
$ cat compression.txt
Hello, World
ちゃんとサンプルコードで使った文字列が書き込まれている。
ちなみに、今回はアーカイブの直下にファイルを配置した。
もし、展開したときにファイルをディレクトリに入れたいときは TarInfo
の引数 name
にスラッシュを含めよう。
まとめ
今回は Python の tarfile モジュールを使って tar ファイルを圧縮・展開してみた。