Python で .zip や .tar.gz などのアーカイブファイル(圧縮ファイル)を扱う方法についてかんたんにまとめました。
仕様と動作の確認に使用した Python のバージョンは Python 3.9.x です。
Python 2 が主流の頃から Python を使い続けてきた方は、アーカイブファイルの操作といえば標準ライブラリの zipfile や tarfile などが真っ先に思い浮かぶ方が多いのではないかと思います。
Python 3 の場合は zipfile や tarfile を使うのもよいですがより高レベルの shutil を使うという選択肢もあります。
shutil は zipfile や tarfile よりもシンプルでわかりやすい(そしてアーカイブ形式によらず共通の)インタフェースを提供しています。
Python 3 でアーカイブファイルの操作が必要になったときは、まず最初に shutil が使えないか検討し、使えたら shutil を使い、使えない場合は zipfile や tarfile を使う、とするのがよいのではないかと思います。
それぞれの使い方をかんたんに見てみましょう。
shutil
shutil は .zip と .tar.gz に対応しています 1 。
両者を共通のシンプルなインタフェース(=関数)で扱えます。
アーカイブファイルを作成する
関数 shutil.make_archive() を使用します。
from shutil import make_archive
# .zip の場合
file_path = make_archive(base_name="/tmp/archived", format="zip", root_dir="/tmp/directory_to_archive")
# => `/tmp/archived.zip`
# .tar.gz の場合
file_path = make_archive(base_name="/tmp/archived", format="gztar", root_dir="/tmp/directory_to_archive")
# => `/tmp/archived.tar.gz`各引数の意味合いは次のとおりです:
base_name: 生成したいアーカイブファイルのパス(拡張子なし)format: アーカイブフォーマットroot_dir: アーカイブしたいディレクトリのパス
format に "zip" を選べば .zip ファイル、 "gztar" を選べば .tar.gz ファイルが作成されます。
format の選択肢にどのようなものがあるのかは環境により異なり shutil.get_archive_formats() で調べることができます。
私の手元の環境では 5 つのフォーマットが利用可能でした:
shutil.get_archive_formats()
# =>
# [
# ('bztar', "bzip2'ed tar-file"),
# ('gztar', "gzip'ed tar-file"),
# ('tar', 'uncompressed tar file'),
# ('xztar', "xz'ed tar-file"),
# ('zip', 'ZIP file'),
# ]これらの引数のうち root_dir は非必須で、指定しなかった場合はカレントディレクトリがアーカイブ対象になります。
make_archive() には他にも多くの引数があるので、実際に使うときには一度確認することをおすすめします。
shutil.make_archive(base_name, format[, root_dir[, base_dir[, verbose[, dry_run[, owner[, group[, logger]]]]]]])make_archive() の戻り値は実際に生成されたアーカイブファイルのパス( str )です。
引数 base_name に format に対応した拡張子が付与されたものになります。
アーカイブファイルを展開する
関数 shutil.unpack_archive() を使用します。
from shutil import unpack_archive
# .zip の場合
unpack_archive(filename="/tmp/archived.zip", extract_dir="/tmp/extracted", format="zip")
# .tar.gz の場合
unpack_archive(filename="/tmp/archived.tar.gz", extract_dir="/tmp/extracted", format="gztar")各引数の意味合いは次のとおりです:
filename: 展開したいアーカイブファイルのパスextract_dir: 展開先のディレクトリのパスformat: アーカイブフォーマット
このうち必須なのは filename だけで、 extract_dir と format は非必須です。
extract_dir を渡さなかった場合、展開先はカレントディレクトリになります。
format を渡さなかった場合、 filename の拡張子に合ったフォーマットが自動的に選択されます。
unpack_archive() の引数は( Python 3.9 では)この 3 つのみです。
shutil.unpack_archive(filename[, extract_dir[, format]])unpack_archive() に戻り値はありません(戻り値 None です)。
zipfile
from zipfile import ZipFileアーカイブファイルを作成する
zipfile.ZipFile オブジェクトのメソッド write() writestr() などを使用します。
`ZipFile()
ファイルをアーカイブファイルに格納する:
# サンプルファイルを用意
with open("/tmp/sample.txt", "w") as f:
f.write("はい、タケコプター!")
with ZipFile(file="/tmp/archived.zip", mode="w") as myzip:
myzip.write(filename="/tmp/sample.txt", arcname="sample.txt") 文字列を直接アーカイブファイルに格納する:
with ZipFile(file="/tmp/archived.zip", mode="w") as myzip:
myzip.writestr(zinfo_or_arcname="sample.txt", data="はい、どこでもドア!") ZipFile() の引数 mode w は書き込みモードを意味します。
w の他に a (追加モード)、 x (排他的な書き込みモード)もあります。
アーカイブファイルを展開する
zipfile.ZipFile オブジェクトのメソッド read() extract() extractall() などを使用します。
個別の中身だけ読み込む:
with ZipFile(file="/tmp/archived.zip", mode="r") as myzip:
data = myzip.read(name="sample2.txt")ファイルを 1 つ取り出す:
with ZipFile(file="/tmp/archived.zip", mode="r") as myzip:
myzip.extract(member="sample2.txt", path="/tmp/extracted")中身をすべて取り出す:
with ZipFile(file="/tmp/archived.zip", mode="r") as myzip:
myzip.extractall(path="/tmp/extracted")ZipFile() の引数 mode r は読み込みモードを意味します。
展開せずに中身を確認する
zipfile.ZipFile オブジェクトのメソッド infolist() namelist() などを使用します。
with ZipFile(file="/tmp/archived.zip", mode="r") as myzip:
infolist = myzip.infolist()
print(infolist) # -> list[ZipInfo]tarfile
import tarfileアーカイブファイルを作成する
tarfile.TarFile オブジェクトのメソッド add() addfile() などを使用します。
tarfile.TarFile オブジェクトは tarfile.open() のコンテキストマネージャで取得できます。
ファイルをアーカイブファイルに格納する:
# サンプルファイルを用意
with open("/tmp/sample.txt", "w") as f:
f.write("はい、タケコプター!")
with tarfile.open(name="/tmp/archived.tar.gz", mode="w:gz") as mytar:
mytar.add(name="/tmp/sample.txt", arcname="sample.txt")文字列を直接アーカイブファイルに格納する:
import io
text = "はい、カムカムキャット!".encode("utf8")
with tarfile.open(name="/tmp/archived.tar.gz", mode="w:gz") as mytar:
tarinfo = tarfile.TarInfo("sample.txt")
tarinfo.size = len(text)
fileobj = io.BytesIO(text)
mytar.addfile(tarinfo, fileobj)tarfile.open() の引数 mode の w:gz は書き込みモードで gzip を意味します。
アーカイブファイルを展開する
tarfile.TarFile オブジェクトのメソッド extract() extractfile() extractall() などを使用します。
個別の中身だけ読み込む:
with tarfile.open(name="/tmp/archived.tar.gz", mode="r:gz") as mytar:
fileobj = mytar.extractfile("sample.txt")
data = fileobj.read()ファイルを 1 つ取り出す:
with tarfile.open(name="/tmp/archived.tar.gz", mode="r:gz") as mytar:
mytar.extract(member="sample.txt", path="/tmp/extracted")中身をすべて取り出す:
with tarfile.open(name="/tmp/archived.tar.gz", mode="r:gz") as mytar:
mytar.extractall(path="/tmp/extracted")tarfile.open() の引数 mode の r:gz は読み込みモードで gzip を意味します。
展開せずに中身を確認する
tarfile.TarFile オブジェクトのメソッド next() getmembers() getnames() などを使用します。
1 件ずつ取得する:
with tarfile.open(name="/tmp/archived.tar.gz", mode="r:gz") as mytar:
while (tarinfo := mytar.next()):
print(tarinfo.name) # -> str全件取得する:
with tarfile.open(name="/tmp/archived.tar.gz", mode="r:gz") as mytar:
members = mytar.getmembers()
print(members) # -> list[TarInfo]コマンドラインで使用する
zipfile モジュールと tarfile モジュールは python -m でコマンドラインから使用することもできます。
どちらも共通のオプションを提供しています。
-c: 作成-e: 展開-l: 確認-t: ファイルが壊れていないかどうかのチェック
zipfile
# 作成する
python -m zipfile -c monty.zip spam.txt eggs.txt
# 展開する
python -m zipfile -e monty.zip target-dir/
# 中身を確認する
python -m zipfile -l monty.ziptarfile
# 作成する
python -m tarfile -c monty.tar spam.txt eggs.txt
# 展開する
python -m tarfile -e monty.tar other-dir/
# 中身を確認する
python -m tarfile -l monty.tarまとめ
ということで、 Python で .zip や .tar.gz などのアーカイブファイル(圧縮ファイル)を扱う方法のまとめでした。
| ライブラリ | 作成 | 展開 | 確認 |
|---|---|---|---|
shutil |
make_archive() |
unpack_archive() |
(なし) |
zipfile |
ZipFile(file, mode="w") |
ZipFile(file, mode="r") |
ZipFile(file, mode="r") |
tarfile |
tarfile.open(file, mode="w:gz") |
tarfile.open(file, mode="r:gz") |
tarfile.open(file, mode="r:gz") |
参考
shutil— High-level file operations — Python 3 documentationtarfile— Read and write tar archive files — Python 3 documentationzipfile— Work with ZIP archives — Python 3 documentation
- 正確には
.zipにはzlibモジュールが、.tar.gzにはzlibモジュールがそれぞれ利用できる必要があります。また、対応するモジュールが利用できる環境ではtar.bz2やtar.xzなど他のアーカイブ形式にも対応しています。↩