Skip to main content

How to Create ZIP Archives of Directories in Python

Creating ZIP archives of directories is a common task for packaging files, creating backups, or sharing data.

This guide explores how to create ZIP archives of directories in Python, covering the simple and recommended shutil.make_archive() method and the more detailed zipfile module for granular control. We'll also touch on using the command line and the zipapp module for creating executable Python archives.

The shutil.make_archive() function provides the simplest and most convenient way to create ZIP archives (and other archive formats) of entire directories:

import shutil

path_to_dir = './my-directory'
output_filename = 'my-zip' # No extension needed here

shutil.make_archive(output_filename, 'zip', path_to_dir)

print('Zip archive of directory created.') # Output: Zip archive of directory created.
  • shutil.make_archive(base_name, format, root_dir):
    • base_name: The name of the archive file without the extension (e.g., 'my-zip'). The extension is added automatically based on the format.
    • format: The archive format. Common options include:
      • 'zip' (requires the zlib module, which is almost always available)
      • 'tar'
      • 'gztar' (gzip-compressed tar, requires zlib)
      • 'bztar' (bzip2-compressed tar, requires bz2)
      • 'xztar' (xz-compressed tar, requires lzma)
    • root_dir: The directory to archive. All paths within the archive will be relative to this directory.
  • The return value of make_archive is the path to the archive file.

Creating ZIP Archives with zipfile (Advanced Control)

The zipfile module gives you fine-grained control over the ZIP archive creation process. This is useful if you need to:

  • Exclude specific files or directories.
  • Set custom compression levels.
  • Add files individually, rather than an entire directory.

Here's an example of recursively zipping a directory with zipfile:

import os
import zipfile

def zip_directory(path, zip_file_handle):
for root, _dirs, files in os.walk(path):
for file in files:
zip_file_handle.write(
os.path.join(root, file),
os.path.relpath(
os.path.join(root, file),
os.path.join(path, '..')
)
)
print(f'Directory {path} zipped successfully')

path_to_dir = './my-directory'
output_filename = 'my-zip.zip'

with zipfile.ZipFile(
output_filename,
'w',
zipfile.ZIP_DEFLATED) as zip_file: # Use ZIP_DEFLATED for compression.
zip_directory(path_to_dir, zip_file)
  • zipfile.ZipFile(output_filename, 'w', zipfile.ZIP_DEFLATED): Opens (or creates) a ZIP file in write mode ('w') with DEFLATED compression (requires the zlib module). You can also use zipfile.ZIP_STORED for no compression.
  • os.walk(path): This efficiently walks through the directory tree, yielding tuples of (root, dirs, files) for each subdirectory.
  • zip_file_handle.write(...): This adds a file to the archive. The important part is calculating the correct archive name (the path within the ZIP file). os.path.relpath() is used to make the paths relative to the directory being zipped.

Using pathlib with zipfile

Using pathlib simplifies the path management with zipfile.

import zipfile
from pathlib import Path

def zip_directory(directory, filename):
directory = Path(directory)
with zipfile.ZipFile(
filename, "w", zipfile.ZIP_DEFLATED
) as zip_file:
for entry in directory.rglob("*"): # rglob for recursive
zip_file.write(entry, entry.relative_to(directory))

print('Zip archive created successfully')

path_to_dir = './my-directory'
output_filename = 'my-zip.zip'
zip_directory(path_to_dir, output_filename)
  • The pathlib module is used to generate file paths, and to get relative paths.
  • This is a cleaner approach that avoids using os.path methods.

Creating ZIP Archives from the Command Line

You can create ZIP archives directly from the command line using Python's built-in zipfile module:

python -m zipfile -c my-zip.zip my-directory  # Include the my-directory itself
python -m zipfile -c my-zip.zip my-directory/* # Exclude the parent my-directory
  • -m zipfile: Runs the zipfile module as a script.
  • -c: Specifies that you want to create an archive.
  • my-zip.zip: The name of the output ZIP file.
  • my-directory: The directory to archive. Using my-directory/* includes the contents of my-directory but not the directory itself in the archive.

Creating Executable Archives with zipapp

The zipapp module (introduced in Python 3.5) allows you to create executable Python applications packaged as ZIP files:

python -m zipapp my_application  # Creates my_application.pyz
python my_application.pyz # Runs the application
  • The zipapp creates a single file that contains all code for the application.
  • This approach is used to create standalone applications using Python.

You can also specify the function to be invoked when you run the .pyz file:

python -m zipapp myapp -m "myapp:main"
python myapp.pyz
  • In this case, the python interpreter will run the main function inside the myapp directory.