【Python】ディレクトリを丸ごとzip圧縮する方法を解説

この記事では、Pythonの標準ライブラリであるzipfileモジュールを使って、基本的なファイルの圧縮方法から、ディレクトリを丸ごと圧縮する方法までをわかりやすく解説します。

さらに、圧縮レベルの設定やパスワード保護付きzipファイルの作成、大規模ディレクトリの圧縮方法など、応用的なテクニックも紹介します。

初心者の方でも安心して取り組めるように、サンプルコードと実行結果を交えながら丁寧に説明しますので、ぜひ最後までご覧ください。

目次から探す

基本的なzip圧縮の方法

Pythonでファイルやディレクトリを圧縮するためには、標準ライブラリのzipfileモジュールを使用します。

このモジュールを使うことで、簡単にzipファイルを作成したり、既存のzipファイルを操作したりすることができます。

まずは、zipfileモジュールの基本的な使い方を見ていきましょう。

zipfileモジュールの基本

zipfile.ZipFileクラスの使い方

zipfileモジュールの中心となるのがzipfile.ZipFileクラスです。

このクラスを使って、新しいzipファイルを作成したり、既存のzipファイルを読み込んだりすることができます。

以下は、zipfile.ZipFileクラスの基本的な使い方の例です。

import zipfile
# 新しいzipファイルを作成
with zipfile.ZipFile('example.zip', 'w') as zipf:
    print("新しいzipファイルを作成しました")
# 既存のzipファイルを読み込む
with zipfile.ZipFile('example.zip', 'r') as zipf:
    print("既存のzipファイルを読み込みました")

この例では、with文を使ってzipfile.ZipFileクラスを利用しています。

with文を使うことで、ファイルのクローズ処理を自動的に行ってくれるため、コードがシンプルになります。

writeメソッドの紹介

zipfile.ZipFileクラスには、ファイルをzipに追加するためのwriteメソッドがあります。

このメソッドを使うことで、指定したファイルをzipファイルに追加することができます。

以下は、writeメソッドの基本的な使い方の例です。

import zipfile
# 新しいzipファイルを作成
with zipfile.ZipFile('example.zip', 'w') as zipf:
    # ファイルをzipに追加
    zipf.write('file1.txt')
    zipf.write('file2.txt')
    print("ファイルをzipに追加しました")

この例では、file1.txtfile2.txtという2つのファイルをexample.zipというzipファイルに追加しています。

ファイル単位での圧縮

次に、具体的なファイル単位での圧縮方法を見ていきましょう。

単一ファイルの圧縮と複数ファイルの圧縮の例をそれぞれ紹介します。

単一ファイルの圧縮例

まずは、単一ファイルを圧縮する方法を見てみましょう。

以下の例では、file1.txtというファイルをexample.zipというzipファイルに圧縮しています。

import zipfile
# 新しいzipファイルを作成
with zipfile.ZipFile('example.zip', 'w') as zipf:
    # 単一ファイルをzipに追加
    zipf.write('file1.txt')
    print("単一ファイルをzipに追加しました")

このコードを実行すると、file1.txtexample.zipに圧縮されます。

複数ファイルの圧縮例

次に、複数ファイルを圧縮する方法を見てみましょう。

以下の例では、file1.txtfile2.txtという2つのファイルをexample.zipというzipファイルに圧縮しています。

import zipfile
# 新しいzipファイルを作成
with zipfile.ZipFile('example.zip', 'w') as zipf:
    # 複数ファイルをzipに追加
    zipf.write('file1.txt')
    zipf.write('file2.txt')
    print("複数ファイルをzipに追加しました")

このコードを実行すると、file1.txtfile2.txtexample.zipに圧縮されます。

以上が、基本的なzip圧縮の方法です。

次のセクションでは、ディレクトリを丸ごと圧縮する方法について詳しく解説します。

ディレクトリを丸ごと圧縮する方法

ディレクトリを丸ごとzip圧縮する方法について解説します。

ディレクトリ内のファイルを再帰的に取得し、それらをzipファイルに追加する手順を詳しく説明します。

ディレクトリ内のファイルを再帰的に取得

ディレクトリ内のファイルを再帰的に取得するためには、Pythonの標準ライブラリであるosモジュールのos.walk関数を使用します。

os.walk関数の使い方

os.walk関数は、指定したディレクトリ内の全てのファイルとサブディレクトリを再帰的に走査します。

以下は基本的な使い方の例です。

import os
for root, dirs, files in os.walk('path/to/directory'):
    print('Current directory:', root)
    print('Subdirectories:', dirs)
    print('Files:', files)

このコードは、指定したディレクトリ内の全てのファイルとサブディレクトリを表示します。

再帰的にファイルを取得する方法

再帰的にファイルを取得するためには、os.walk関数を使用して各ファイルのフルパスをリストに追加します。

以下はその例です。

import os
def get_all_files(directory):
    file_paths = []
    for root, dirs, files in os.walk(directory):
        for file in files:
            file_paths.append(os.path.join(root, file))
    return file_paths
# 使用例
all_files = get_all_files('path/to/directory')
for file in all_files:
    print(file)

この関数は、指定したディレクトリ内の全てのファイルのフルパスをリストとして返します。

取得したファイルをzipに追加

次に、取得したファイルをzipファイルに追加する方法を説明します。

zipfile.ZipFileとos.walkの組み合わせ

zipfile.ZipFileクラスos.walk関数を組み合わせて、ディレクトリ内の全てのファイルをzipファイルに追加します。

以下はその例です。

import os
import zipfile
def zip_directory(directory, zip_name):
    with zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED) as zipf:
        for root, dirs, files in os.walk(directory):
            for file in files:
                file_path = os.path.join(root, file)
                zipf.write(file_path, os.path.relpath(file_path, directory))
# 使用例
zip_directory('path/to/directory', 'output.zip')

この関数は、指定したディレクトリ内の全てのファイルをoutput.zipという名前のzipファイルに圧縮します。

フルパスと相対パスの扱い

zipファイルに追加する際に、フルパスではなく相対パスを使用することで、zipファイル内のディレクトリ構造を保つことができます。

上記の例では、os.path.relpath関数を使用して相対パスを取得しています。

完全なスクリプトの例

ここまでの内容をまとめて、ディレクトリを丸ごとzip圧縮する完全なスクリプトを紹介します。

スクリプト全体の紹介

以下が完全なスクリプトです。

import os
import zipfile
def get_all_files(directory):
    file_paths = []
    for root, dirs, files in os.walk(directory):
        for file in files:
            file_paths.append(os.path.join(root, file))
    return file_paths
def zip_directory(directory, zip_name):
    with zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED) as zipf:
        for root, dirs, files in os.walk(directory):
            for file in files:
                file_path = os.path.join(root, file)
                zipf.write(file_path, os.path.relpath(file_path, directory))
# 使用例
if __name__ == "__main__":
    directory_to_zip = 'path/to/directory'
    output_zip_file = 'output.zip'
    zip_directory(directory_to_zip, output_zip_file)
    print(f'{directory_to_zip} has been compressed into {output_zip_file}')

実行方法と結果の確認

このスクリプトを実行することで、指定したディレクトリがzipファイルに圧縮されます。

以下は実行例です。

$ python zip_directory.py
path/to/directory has been compressed into output.zip

このようにして、ディレクトリを丸ごとzip圧縮することができます。

応用編

圧縮レベルの設定

圧縮レベルの指定方法

Pythonのzipfileモジュールでは、圧縮レベルを指定することができます。

圧縮レベルは0から9までの整数で指定し、0は圧縮なし、9は最高圧縮率を意味します。

圧縮レベルを指定するには、zipfile.ZipFileクラスcompresslevel引数を使用します。

以下は、圧縮レベルを指定してファイルを圧縮する例です。

import zipfile
# 圧縮レベルを指定してzipファイルを作成
with zipfile.ZipFile('example.zip', 'w', zipfile.ZIP_DEFLATED, compresslevel=9) as zipf:
    zipf.write('example.txt')

圧縮レベルの違いによるファイルサイズの比較

圧縮レベルの違いによって、生成されるzipファイルのサイズがどのように変わるかを比較してみましょう。

以下の例では、圧縮レベル0と9でファイルを圧縮し、そのサイズを比較します。

import zipfile
import os
# 圧縮レベル0でファイルを圧縮
with zipfile.ZipFile('example_level0.zip', 'w', zipfile.ZIP_DEFLATED, compresslevel=0) as zipf:
    zipf.write('example.txt')
# 圧縮レベル9でファイルを圧縮
with zipfile.ZipFile('example_level9.zip', 'w', zipfile.ZIP_DEFLATED, compresslevel=9) as zipf:
    zipf.write('example.txt')
# ファイルサイズの比較
size_level0 = os.path.getsize('example_level0.zip')
size_level9 = os.path.getsize('example_level9.zip')
print(f'圧縮レベル0のファイルサイズ: {size_level0} bytes')
print(f'圧縮レベル9のファイルサイズ: {size_level9} bytes')

パスワード保護付きzipファイルの作成

zipfileモジュールの制限

Pythonの標準ライブラリであるzipfileモジュールは、パスワード保護付きのzipファイルを作成する機能をサポートしていません。

そのため、パスワード保護付きのzipファイルを作成するには、外部ライブラリを使用する必要があります。

pyminizipライブラリの紹介と使用方法

pyminizipは、パスワード保護付きのzipファイルを作成できる外部ライブラリです。

以下の手順でpyminizipをインストールし、使用する方法を紹介します。

  1. pyminizipのインストール
pip install pyminizip
  1. パスワード保護付きzipファイルの作成
import pyminizip
# パスワード保護付きzipファイルを作成
src_file = 'example.txt'
dst_file = 'example_protected.zip'
password = 'your_password'
compression_level = 5  # 圧縮レベルは0から9の範囲で指定
pyminizip.compress(src_file, None, dst_file, password, compression_level)

大規模ディレクトリの圧縮

メモリ使用量の最適化

大規模なディレクトリを圧縮する際には、メモリ使用量を最適化することが重要です。

zipfileモジュールを使用する場合、ファイルを一度にメモリに読み込むのではなく、ストリームとして処理することでメモリ使用量を抑えることができます。

以下は、ストリームを使用して大規模ディレクトリを圧縮する例です。

import zipfile
import os
def zip_directory(directory_path, zip_path):
    with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
        for root, dirs, files in os.walk(directory_path):
            for file in files:
                file_path = os.path.join(root, file)
                zipf.write(file_path, os.path.relpath(file_path, directory_path))
# 大規模ディレクトリを圧縮
zip_directory('large_directory', 'large_directory.zip')

圧縮処理の進捗表示

大規模なディレクトリを圧縮する際には、進捗状況を表示することでユーザーに安心感を与えることができます。

以下は、圧縮処理の進捗を表示する例です。

import zipfile
import os
from tqdm import tqdm
def zip_directory_with_progress(directory_path, zip_path):
    file_list = []
    for root, dirs, files in os.walk(directory_path):
        for file in files:
            file_list.append(os.path.join(root, file))
    with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
        for file in tqdm(file_list, desc="圧縮中"):
            zipf.write(file, os.path.relpath(file, directory_path))
# 大規模ディレクトリを圧縮し、進捗を表示
zip_directory_with_progress('large_directory', 'large_directory_with_progress.zip')

このようにして、Pythonを使ってディレクトリを丸ごとzip圧縮する方法を学びました。

基本的な圧縮方法から、応用的な圧縮レベルの設定やパスワード保護、大規模ディレクトリの圧縮まで、さまざまなテクニックを駆使して効率的に圧縮処理を行うことができます。

トラブルシューティング

Pythonでディレクトリを丸ごとzip圧縮する際に遭遇する可能性のあるトラブルとその対処法について解説します。

よくあるエラーと対処法

ファイルパスの長さ制限

Windows環境では、ファイルパスの長さが260文字を超えるとエラーが発生することがあります。

この問題を回避するためには、以下の方法があります。

  1. 短いパスを使用する: 圧縮対象のディレクトリをルートディレクトリに近い場所に移動することで、パスの長さを短くすることができます。
  2. 長いパスをサポートする設定を有効にする: Windows 10以降では、レジストリ設定を変更することで長いパスをサポートすることができます。
import os
import zipfile
def zip_directory(directory_path, zip_path):
    with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
        for root, dirs, files in os.walk(directory_path):
            for file in files:
                file_path = os.path.join(root, file)
                arcname = os.path.relpath(file_path, start=directory_path)
                zipf.write(file_path, arcname)
# 使用例
zip_directory('C:\\path\\to\\your\\directory', 'C:\\path\\to\\your\\output.zip')

権限エラー

ファイルやディレクトリに対するアクセス権限が不足している場合、権限エラーが発生することがあります。

この問題を回避するためには、以下の方法があります。

  1. 管理者権限で実行する: スクリプトを管理者権限で実行することで、アクセス権限の問題を回避できます。
  2. アクセス権限を変更する: 対象のファイルやディレクトリのアクセス権限を変更して、読み取り・書き込み権限を付与します。
import os
import zipfile
def zip_directory(directory_path, zip_path):
    try:
        with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
            for root, dirs, files in os.walk(directory_path):
                for file in files:
                    file_path = os.path.join(root, file)
                    arcname = os.path.relpath(file_path, start=directory_path)
                    zipf.write(file_path, arcname)
    except PermissionError as e:
        print(f"権限エラーが発生しました: {e}")
# 使用例
zip_directory('C:\\path\\to\\your\\directory', 'C:\\path\\to\\your\\output.zip')

デバッグ方法

ログの出力

デバッグを行う際には、ログを出力することで問題の原因を特定しやすくなります。

Pythonのloggingモジュールを使用して、ログを出力する方法を紹介します。

import os
import zipfile
import logging
# ログの設定
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
def zip_directory(directory_path, zip_path):
    try:
        with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
            for root, dirs, files in os.walk(directory_path):
                for file in files:
                    file_path = os.path.join(root, file)
                    arcname = os.path.relpath(file_path, start=directory_path)
                    logging.debug(f"Adding {file_path} as {arcname}")
                    zipf.write(file_path, arcname)
    except Exception as e:
        logging.error(f"エラーが発生しました: {e}")
# 使用例
zip_directory('C:\\path\\to\\your\\directory', 'C:\\path\\to\\your\\output.zip')

デバッグツールの紹介

デバッグツールを使用することで、コードの実行中に変数の値を確認したり、ステップ実行を行ったりすることができます。

以下に代表的なデバッグツールを紹介します。

  1. PDB (Python Debugger): Python標準のデバッガで、コマンドラインから使用できます。
import pdb
def zip_directory(directory_path, zip_path):
    pdb.set_trace()  # デバッグ開始
    with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
        for root, dirs, files in os.walk(directory_path):
            for file in files:
                file_path = os.path.join(root, file)
                arcname = os.path.relpath(file_path, start=directory_path)
                zipf.write(file_path, arcname)
# 使用例
zip_directory('C:\\path\\to\\your\\directory', 'C:\\path\\to\\your\\output.zip')
  1. Visual Studio Code: VSCodeには強力なデバッグ機能があり、ブレークポイントの設定や変数の監視が簡単に行えます。
  2. PyCharm: PyCharmもまた、豊富なデバッグ機能を提供しており、特に大規模なプロジェクトでのデバッグに適しています。

これらのツールを活用することで、効率的にデバッグを行い、問題を迅速に解決することができます。

目次から探す