Python標準ライブラリ(zip/shutilモジュール)でファイル管理しよう

スポンサーリンク
Python標準ライブラリ_zip_shutil_ファイルのアーカイブ Python

Python標準ライブラリ(zip/shutilモジュール)でファイル管理しよう

<本サイト「Pythonでもっと自由を」のコンセプト>

本サイトは現在の人気No.1プログラミング言語Pythonをつかって作業を自動化効率アップしましょうというコンセプトを基にさまざまなライブラリ(モジュール)を紹介していきます。

・Pythonという言語にはこれらの私たちの身近なアプリケーションを自動化して

  くれるさまざまなライブラリ・モジュールが提供されている。

・Pythonを使うことで、これまでに、何時間もかけていた作業が数秒で終わらせ

 ることもできるかもしれない。


ビジネスシーンにおいて、大量のデータを整理して管理したい、大きいサイズのファイルを相手に転送したいといったことは頻繁にあるとあると思います。

きっと、Windowsなどのエクスプローラの標準機能「送る圧縮(zip形式)フォルダ」でアーカイブ化する、または専用のフリーウェアなどを使って圧縮・解凍するといった方法をとられているのではないでしょうか。

実はPythonを使ってファイル・フォルダのアーカイブ(解凍・圧縮)する方法もあります。それは、標準ライブラリとして用意されているzipfile/shutilというモジュールを使う方法です。

今回の記事ではzip/shutilモジュールのファイルアーカイブ化に特化した使い方(※)を紹介したいと思います。

※両ジュールはとても奥深く数多のクラスやメソッドなどが用意されていますので全てを紹介することはできません。これだけは知っておきたいという実行方法を厳選して紹介することにします。

この記事を読むことで次のことがわかるようになります。

この記事で学べること
  • zipfileモジュールでファイルを圧縮・解凍をする方法
  • shutilモジュールでファイル・フォルダを圧縮・解凍をする方法
  • 両モジュールの違いと使い分けについて
スポンサーリンク

1.zipfileモジュールによるアーカイブ

zipfileモジュールの使い方について解説します。

Python公式ドキュメント(zipfile)は次の通りですので適宜参照ください。

Python公式ドキュメント(zipfileモジュール)

https://docs.python.org/3/library/zipfile.html?highlight=zipfile#module-zipfile

Pythonの標準ライブラリですのでインストールは必要なくインポートするだけで使用できます。

zipfileモジュールは次のようにしてインポートします。

import zipfile

特にエラーメッセージがでなければインポート成功です。

まず、zipfileモジュールの使い方の概要について説明します。

圧縮する場合(新規作成)

  1. ZipFileオブジェクトを作成する(空のZipファイルが作成)
  2. 空のZipFileオブジェクトに圧縮したファイルを追加する
  3. ZipInfoオブジェクトで属性の詳細を設定する(任意)

解凍する場合

  1. Zipファイルの全て内容を一度に解凍する。
  2. Zipファイルの特定のファイルを指定して解凍する

それでは、Zipモジュールをつかったファイルの圧縮・解凍について具体的なオブジェクトやクラス、メソッドの使い方を説明していきます。

なお、ここで紹介しているものは、本ライブラリを使う上で最低限必要なものを厳選しています。 引数のオプションなど詳細については公式ドキュメントを参照して下さい。

1.1 zipfileモジュール

1.1.1 zipファイル(ZipFileオブジェクト)を生成する

Documentオブジェクト

ZipFileオブジェクト = zipfile.ZipFile(file, mode, cumpression)関数


引数1:file:Zip圧縮するファイル名の指定

引数2:mode:書き込みモード(w), 読み込み専用モード(r), 追記モード(a)を指定

引数3:compression:圧縮タイプを指定

API Document[ZipFileオブジェクト]

引数:modeの指定一覧は次の通りとなります。

zipfile.ZipFile_modeの指定オプション
表1 引数modeのオプション指定一覧

引数:compressionの指定一覧は次の通りとなります。

zipfile.ZipFile_compressionの指定オプション
表2 引数compressionのオプション指定一覧

1.1.2 ZipFileオブジェクトにファイルを追加する

ZipFileオブジェクト(write関数)

ZipFileオブジェクト.write(filename, arcname)関数


引数1:filename:追加したいファイル名(カレントディレクトリでない場合はパスも含めて指定する)

引数2:arcname:アーカイブ先でのファイル名とその相対パスを指定する

次の例は新規zipファイルを書込みモード(‘w‘)で作成し、そこに1つファイル追加しています。

import zipfile

FILE = testImage1.jpg
#------------------------------------------------------------------------------
# 新規のZipFileオブジェクトを書込みモードで開く
with zipfile.ZipFIle('zip_arc.zip', 'w', zipfile.ZIP_DEFLATED) as zipf:
    zipf.write(FILE, testImage1.jpg)

ZipFileオブジェクトにファイルを追加するイメージ図です。

zipfile_writeメソッドのイメージ図
図2 ZipFileオブジェクトのwrite関数の使用例

次は既存のzipファイルを追記モード(‘a‘)で開き、2つファイルを追加しています。

ZipFileモジュールでは、一度に複数のファイルを追加することはできず、一つずつwrite関数で追加していく必要があります。

import zipfile

#------------------------------------------------------------------------------
# 既存のZipFileオブジェクトを追記モードで開く
with zipfile.ZipFIle('zip_arc.zip', 'a', zipfile.ZIP_DEFLATED) as zipf:
    zipf.write(testImage2, testImage2.jpg)          # 既存のZipFileオブジェクトに追加する
    zipf.write(testImage3, testImage3.jpg)          # 既存のZipFileオブジェクトに追加する


1.1.3 ZipFileオブジェクトを解凍する

(1) 一度に全ての圧縮ファイルを解凍する場合

ZipFileオブジェクト(extractall関数)

ZipFileオブジェクト.extractall(path)関数


引数1:path:解凍先のパスを指定

次はextractall関数で、アーカイブファイル(zip_arc.zip)を一度に解凍しています。

import zipfile
#------------------------------------------------------------------------------
with zipfile.ZipFIle('zip_arc.zip', 'r) as zipf:    # 引数compressionは省略してOK
    zipf.extractall('unzip')                        # 解凍先フォルダを指定
zipfile_extractallのイメージ図
図3 ZipFileオブジェクトのextractall関数の使用例

(2) 特定の圧縮ファイルを指定して解凍する場合

ZipFileオブジェクト(extract関数)

ZipFileオブジェクト.extract(member, path)関数


引数1:member:解凍したいファイル名もしくはZIpInfoオブジェクト(後述)を指定する

引数2:path:解凍先のパスを指定

次はextract関数で、引数:memberにZipInfoオブジェクトを個別に指定し解凍する例です。

import zipfile

with zipfile.ZipFile('test/photo_arc.zip') as zipf:
    zinfos = zipf.infolist()              # ZipInfoオブジェクトを取得(詳細は後述)
    zipf.extract(zinfos[2], 'unzip')      # ZipInfoオブジェクトを個別に指定し解凍する


解凍する場合は、いずれの場合も、ZipFileオブジェクトは’r’(読取りモード)で取得します。また、指定した解凍先フォルダが存在していなければ新規作成されます。

1.1.4 ZipInfoオブジェクトの取得と操作

ZipFileオブジェクト(infolist関数)

ZipInfoオブジェクト = ZipFileオブジェクト.infolist()関数


API Document[ZipInfoオブジェクト]

ZipInfoオブジェクトとはアーカイブファイルの情報(ファイル名やサイズなど)です。

複数のファイルがある場合は<>一つがZipInfoオブジェクトで次のようにリスト形式で出力される。

[<項目名1=値1, 項目名2=値2 ・・・ >, <>,<>,・・・]

特定のZipInfoオブジェクトを指定する場合は、ZipInfoオブジェクト[index]のようにインデックス

で取得できます。

ZipInfoオブジェクトの主なプロパティは次のようなものがあります。

オブジェクトプロパティ機能
ZipInfoオブジェクトfilenameプロパティファイル名の取得と設定
ZipInfoオブジェクトflag_bitsプロパティZipファイルのフラッグビット情報の取得
ZipInfoオブジェクトcompress_typeプロパティZipファイルの圧縮形式の取得
ZipInfoオブジェクトcompress_sizeプロパティZipファイルのサイズの取得
表3 ZipInfoオブジェクトの主なプロパティ

次はZipInfoオブジェクトの主なプロパティを示したものです。

infolist()関数によるZipInfoオブジェクトの取得とそのプロパティによりファイル名、圧縮形式、サイズを取得しています。

import zipfile

with zipfile.ZipFile('zip_arc.zip') as zipf:
    
    print(zipf.infolist())	# ZipInfoオブジェクトを表示
# >>[<ZipInfo filename='img1.jpg' compress_type=deflate filemode='-rw-rw-rw-' file_size=7133compress_size=7106>, <ZipInfo ....<2つめのZipInfoオブジェクト><3つめのZipInfoオブジェクト> ]

    zinfos = zf.infolist()	# ZipInfoオブジェクトを取得
    print(zinfos[0])            # 一つ目のZipファイルのZipInfoを選択して表示
# >><ZipInfo filename='img1.jpg' compress_type=deflate filemode='-rw-rw-rw-' file_size=7133 compress_size=7106>

#-------------------------------------------------------------------------------------------------
    print(zinfos[0].filename)		# ファイル名を取得    >> img1.jpg
    print(zinfos[0].compress_type)	# 圧縮形式を取得    >> 8
    print(zinfos[0].compress_size)	# 圧縮サイズを取得    >> 7106

また、次のようにflag_bitsプロパティを利用して文字コードの情報を取得することにより文字化け

対策をすることができます。if句で旧文字コード(cp437)であるかを調べ、そうであればStrオブジェクトのencode/decodeプロパティで文字コードをcp932へ変換しています。

import zipfile

with zipfile.ZipFile('zip_arc.zip') as zipf:
    for zinfo in zipf.infolist():        # ZipInfoオブジェクトを取得
        if not zinfo.flag_bits & 0x800:  # flag_bitsプロパティで文字コードを取得
	    # 文字コードが(cp437)だった場合はcp932へ変換する
            # strオブジェクトのプロパティencode/decodeでcp932に変換
            # 変換後のファイル名をfilenameプロパティで再度し直す
            zinfo.filename = zinfo.filename.encode('cp437').decode('cp932')
        
        zf.extract(zinfo, 'unzip')

1.1.5 ZipFileオブジェクトその他の属性

ZipFileオブジェクトのその他の属性(メソッド)は以下のようなものがあります。他にも数多ありますので必要に応じて公式Documentを参照して下さい。

オブジェクトメソッド・プロパティ機能
ZipFileオブジェクトcloseメソッドwith構文を使用しないでZipFileオブジェクトを取得した場合は
必ず閉じる必要がある
ZipFileオブジェクトopenメソッド既存のZipFileオブジェクト(Zipファイル)を開く
ZipFileオブジェクトnamelistメソッド圧縮したファイル名を取得する(複数ある場合はリスト形式で戻る)
表4 ZipFileオブジェクトの主なメソッド・プロパティ

2. shutilモジュールによるアーカイブ

Python_基本文法_内包表記

shutilモジュールの使い方について解説します。

shutilはアーカイブに特化したモジュールというわけではなく、他にも高次なファイル操作を提供するクラスやメソッドが多数あります。

Python公式ドキュメント(shutil)は次の通りですので適宜参照ください。

Python公式ドキュメント(shutilモジュール)

https://docs.python.org/3/library/shutil.html?highlight=shutil#module-shutil

Pythonの標準ライブラリですのでインストールは必要なくインポートするだけで使用できます。

shutilモジュールは次のようにしてインポートします。

import shutil

特にエラーメッセージがでなければインポート成功です。

まず、shutilモジュールの使い方ですが、shutilのよる圧縮・解凍は先のzipfileモジュールによる手順とは異なり中間オブジェクト(ZipFileオブジェクト)の生成は不要で、関数の引数にアーカイブファイル名、対象フォルダを指定するだけで済みます。

それでは、shutilモジュールを用いたファイルの圧縮・解凍について具体的なオブジェクトやクラス、メソッドの使い方を説明していきます。

2.1 shutilモジュール

2.1.1 フォルダの中身をまとめて圧縮する

shutilモジュール make_archive関数(1)

shutil.make_archive(base_name, format, root_dir)


引数1:base_name:作成するアーカイブファイルの名前を指定する。※注意点としては、拡張子は指定しないこと。

引数2:format:アーカイブ方式を指定する。ZIP圧縮であれば「zip」、tar..gz圧縮であれば「gztar」を指定するその他、bztar/xztarがある

引数3:root_dir:アーカイブ対象となるディレクトリを指定する。対象のディレクトリ以下に含まれるフォルダーやファイルがまとめて圧縮される

次の例はフォルダの中身をまとめて圧縮するコード例です。zipfileモジュールではまとめて一度に処理することはできませんがshutilモジュールのmake_archive関数を使うと一行で対応することができます。

引数:root_dirは対象のファイルが保存されているディレクトリを指定します。

図4の例では、引数:root_dirには、target_folderを指定してその中身のファイルを処理しています。

import shutil

# base_dirフォルダは省略した場合
# 引数root_dirには圧縮対象のファイルやフォルダを含むディレクトリを指定する
shutil.make_archive('zip_arc', 'zip', 'target_folder')

target_folderそのものではなくその中身が圧縮対象になります。

shutil_make_archive_1
図4 target_folder内の複数ファイルを圧縮する例

2.1.2 フォルダごと圧縮する

shutilモジュール make_archive関数(2)

shutil.make_archive(base_name, format, root_dir, base_dir)


引数1:base_name:作成するアーカイブファイルの名前を指定する。※注意点としては、拡張子は指定しないこと。

引数2:format:アーカイブ方式を指定する。ZIP圧縮であれば「zip」、tar..gz圧縮であれば「gztar」その他、bztar/xztarがある

引数3:root_dir:アーカイブ対象となるディレクトリを指定する。対象のディレクトリ以下に含まれるフォルダーやファイルがまとめて圧縮される。

引数4:base_dir:アーカイブを開始するディレクトリを指定する。

では、フォルダーごと(図の例ではtarget_folder)圧縮することはできないかというと勿論そのようなことはなく、もう一つ引数を追加(base_dir)することで対応できます。

次のコードと図5はその例になります。まず、引数:root_dirには対象のフォルダの親ディレクトリ(一つ上の階層のフォルダ)を指定します、そして追加した引数:base_dirに対象フォルダを指定します。

つまり、root_dirには対象フォルダの親ディレクトリである(Current_dir)、そしてbase_dirには対象フォルダである(target_folder)を指定します。

import shutil

#base_dirフォルダを指定した場合
# 引数root_dirには圧縮対象フォルダの親ディレクトリを指定
# 引数base_dirには圧縮対象フォルダを指定する
shutil.make_archive('zip_arc', 'zip', 'Current_dir'', 'target_folder')

target_folderそのものが圧縮対象になります。

shutil_make_archive_2
図5 target_folderを圧縮する例

2.1.3 圧縮フォルダを解凍する

shutilモジュール unpack_archive関数

shutil.unpack_archive(filename, extract_dir)


引数1:filename:解凍したいアーカイブファイル(必要に応じてパスも付けて指定する)

引数2:extract_dir:解凍先ディレクトリ

Unpack_archiveの使用例になります。引数:filenameに解凍対象のファイル名(zip_arc.zip)を、

引数:extract_dirに解凍先のディレクトリ(unzip)を指定しています。指定した解凍先が存在しなければ自動で作成されます。

import shutil

shutil.unpack_archive('zip_arc.zip', 'unzip')

unpack_archive関数を使った解凍はシンプルですが、元になる圧縮ファイルの中身によって展開内容が異なります。図6はフォルダの中身を圧縮したアーカイブファイルを解凍した例です。

shutil_unpack_archive_1
図6 zip_arc.ziipをunzipに解凍する例1

図7はフォルダごと圧縮したアーカイブファイルを解凍した例です。

shutil_unpack_archive_2
図7 zip_arc.ziipをunzipに解凍する例2

3. zipfile/shutilモジュールの使い分けについて

ここで、zipfileとshutilモジュールの得意・苦手を比較して使い分けましょう。簡単にまとめると次のようになります。


 【zipfileモジュール】

得意:ファイル毎の圧縮・解凍ができまた、細かい設定や文字化け対策ができる

苦手:フォルダごと一気に圧縮することができない。(ファイルを一つずつ圧縮する必要があるためコード量が増える)

 【shutilモジュール】

得意:フォルダごと一気にアーカイブできる。(Windowsのエクスプローラでの圧縮方法に近いイメージ)

苦手:zipfileモジュールのようなファイル毎に詳細設定ができない。

Windowsエクスプローラの用に効率的にアーカイブする場合はshutil、個別ファイル毎の処理や文字化け対策が必要になるのであればzipfileといった使い分けができるのではないでしょうか。

4. まとめ

いかがでしたでしょうか?

今回はPythonの標準ライブラリであるzipfile/shutilモジュールを使って、アーカイブファイルの作成をする方法についてまとめました。

➀ zipfileモジュールでファイルを圧縮・解凍をする方法

② shutilモジュールでファイル・フォルダを圧縮・解凍をする方法

➂ 両モジュールの違いと使い分けについて

Pythonを使って大量のファイルを管理整理行うなどの処理を自動化したいときには役立つ機能を提供してくれるモジュールだと思います。是非活用してみてください。

最後までお読み頂きありがとうございました。

タイトルとURLをコピーしました