Python(zipfile/shutil)でフォルダ圧縮してzipにする

プログラミングのコードが多数登場するような記事はこのサイトであまり書いてこなかった気がするけど、今回はPythonのフォルダ圧縮について見ていきたいなあと思う。Pythonの記事は以前こんなの書きましたね。

これはどんなことできんの?っていう内容だったけど、今回はフォルダ圧縮をピンポイントでいこうと思う。

Pythonでフォルダを圧縮する

フォルダを圧縮してzip形式にするには、zipfile使ったりshutil使ったりする方法があったりすると思うけど、今回は2つ使ってやってみたいと思う。

zipfileを使ってフォルダをzipに圧縮する

まずはzipfile。

zipfile

なんか見てみたけど、このzipfileって結構扱い面倒ですね。フォルダの中身まで見てそれらを一括でzipにしてくれるっていうのは装備されていないのか・・・今回はフォルダの中身を含めて圧縮して欲しいからちょっとやってみた。

import zipfile,os

# zipファイル作成
with zipfile.ZipFile('好きな圧縮ファイル名.zip','w') as zip_f:
  # 圧縮したいディレクトリへ移動
  os.chdir('/Users/U/desktop')
  # フォルダを指定、フォルダの中身まで圧縮に含まれるように指定
  for folder, subfolders, files in os.walk('圧縮したいフォルダ名'):
    zip_f.write(folder)
    for file in files:
        zip_f.write(os.path.join(folder,file))

いちいちfor文で中身を見ていく記述をしているのがなんとも言えないですね。zipfileの使い方のイメージとしてはこんな感じなのか。。。

  1. zipfileを作成
  2. 作成したzipファイルに圧縮したいファイルを突っ込んでいく

ただ普通にフォルダ指定した場合は、そのフォルダだけ指定してもその中身は空になったzipファイルが作成されるという感じでした。だからこんな書き方になってしまったうーむ。ちなみにこんな感じでフォルダを指定してやってみるとフォルダの中身までzipに突っ込まれました。

import zipfile,os

# zipファイル作成
with zipfile.ZipFile('zipped_folder.zip','w') as zip_f:
  # 圧縮したいディレクトリへ移動
  os.chdir('/Users/U/desktop')
  # フォルダを指定、フォルダの中身まで圧縮に含まれるように指定
  for folder, subfolders, files in os.walk('test_folder'):
    zip_f.write(folder)
    for file in files:
        zip_f.write(os.path.join(folder,file))

開いてみてもフォルダの中身までちゃんとありますね。

なんか結構面倒な使い方な気がしてならないけど、どうなんだろう。ちなみに次にやるshutilだと1行で済んでわろた・・・

shutilを使ってフォルダをzipに圧縮する

次はshutilを使ったフォルダ圧縮。使い方を諸々見たかったらドキュメントを覗いてみるといいね。

今回使ってやろうと思うのはこのshutilの中にあるフォルダをzipなんかにしてくれるmake_archive関数。Githubでコードを見るとこれかな。引数多いなあ・・・

make_archive

で、まあ引数が色々あるから諸々指定できそうだけど、zipにするだけならこれだけでいいか。1行で書けるから楽でいいね。

import shutil

shutil.make_archive(生成される名前, 'zip'[, root_dir=圧縮したいフォルダのパス])

実際に試してみる。/Users/U/Desktop/test_folderをzipped_folderっていう名前でzipにする。

import shutil
shutil.make_archive('zipped_folder', 'zip', root_dir='/Users/U/Desktop/test_folder')

実行してみるとこんな感じでzipが作成されますね。

shutilのmake_archiveはスレッドセーフでないみたい?

楽にかけて便利だなあって思うけど、どうやらmake_archiveはマルチスレッドセーフじゃないみたいですね。

shutil.make_archiveをマルチスレッドで走らせるとランダムにファイルが抜ける

Pythonのshutil.make_archiveはスレッドセーフではない?

知らないとハマりそうな気もするから、知っておいた方が良き。

まとめ

Pythonを使ってフォルダ圧縮する方法をちょろっと見てみたけど、どうだろうか。面倒な部分もあったけどちゃんと書けばまあ圧縮してzipにしてくれます。ただzipfileの扱いが面倒なのとshutilはshutilでマルチスレッドセーフじゃない感もあったりするからなんとも言えない・・・