Pythonでディレクトリ圧縮(zipファイル作成)

Windowsのエクスプローラを使っていると、コンテキストメニューからzipアーカイブファイルを作成することができますが、同じことをPythonでやってみたいと思います。

ディレクトリを圧縮する場合、shutilモジュールの.make_archive()メソッドも使えます。具体的にはこちらの記述で"xztar"(format引数)を"zip"に変更するだけです。
ただしshutilではファイルの種類や更新時刻など特定の条件を指定するなど細かい制御が難しいので、ここではzipfileモジュールを使うことにします。

ここではcreate_zipfile()関数が、指定されたディレクトリに対してzipアーカイブファイルを作成します。使い方はmainの部分に例示しています。
zipfileは圧縮を行うためのモジュールで、対象のファイルパスをアーカイブファイル内の(相対)パスと合わせて指定することで、元の階層を維持することができます。

先にスクリプト全体を記載しておきます。

以下ポイントを簡単に解説します。

ファイルの検索

特定ディレクトリパス以下に含まれるすべてのファイルパスを再帰的に取得するために、os.walk()を利用しています。
ファイルシステム(木構造)の階層を辿って、見つかったファイルのパスを順次yieldで返してきます。

ちなみに、同じ方法でサブディレクトリのパス(この例ではdirs)を取得することもできます。

ファイルの圧縮(アーカイブファイルの作成)

zipfile.ZipFileオブジェクトをファイルストリームとして開き、write()メソッドで書庫(アーカイブファイル)にファイルを追加していきます。

サポートされている圧縮方法はいくつかありますが、ここでは一般的なもの(zipfile.ZIP_DEFLATED、gzip互換)を指定しています。デフォルト値(compressionを省略した場合)は圧縮されない(単一の書庫ファイルにまとめられるだけ)なので注意して下さい。
with構文で呼んでいるのでストリームのクローズ(f.close())は不要です。

ディレクトリの削除

ファイルシステムの操作で地味に面倒なのが、削除操作ですね。
普通にos.rmdir()を呼んでしまうと、ディレクトリが空でない場合(中にファイルが存在する場合)がエラーになります。

shutil.rmtree()を使うとファイルシステムを辿って削除を行うので、
幾分か楽に削除操作ができるようになります。ただし、この場合はいわゆるリサイクル(ゴミ箱に移動)ではなく、即削除になってしまう点には注意が必要です。
また、権限不足はエラーになる(当たり前ですが)など、万能というわけではありません。