The zipfile module creates, reads, and extracts ZIP archives. No external tools needed.

Reading ZIP Files

import zipfile
 
# List contents
with zipfile.ZipFile('archive.zip', 'r') as zf:
    print(zf.namelist())
    # ['file1.txt', 'folder/file2.txt']
 
# Get info about a file
with zipfile.ZipFile('archive.zip', 'r') as zf:
    info = zf.getinfo('file1.txt')
    print(f"Size: {info.file_size}")
    print(f"Compressed: {info.compress_size}")

Extracting Files

import zipfile
 
# Extract all
with zipfile.ZipFile('archive.zip', 'r') as zf:
    zf.extractall('output_dir')
 
# Extract single file
with zipfile.ZipFile('archive.zip', 'r') as zf:
    zf.extract('file1.txt', 'output_dir')
 
# Read file without extracting
with zipfile.ZipFile('archive.zip', 'r') as zf:
    content = zf.read('file1.txt')
    print(content.decode('utf-8'))

Creating ZIP Files

import zipfile
 
# Create new archive
with zipfile.ZipFile('new.zip', 'w') as zf:
    zf.write('file1.txt')
    zf.write('file2.txt')
 
# With compression
with zipfile.ZipFile('compressed.zip', 'w', zipfile.ZIP_DEFLATED) as zf:
    zf.write('large_file.txt')
 
# Add with different archive name
with zipfile.ZipFile('archive.zip', 'w') as zf:
    zf.write('local/path/file.txt', 'renamed.txt')

Write String Content

import zipfile
 
with zipfile.ZipFile('archive.zip', 'w') as zf:
    # Write string directly
    zf.writestr('hello.txt', 'Hello, World!')
    
    # Write bytes
    zf.writestr('data.bin', b'\x00\x01\x02\x03')

Append to Existing ZIP

import zipfile
 
with zipfile.ZipFile('existing.zip', 'a') as zf:
    zf.write('new_file.txt')

Compression Options

import zipfile
 
# No compression (fastest)
with zipfile.ZipFile('store.zip', 'w', zipfile.ZIP_STORED) as zf:
    zf.write('file.txt')
 
# DEFLATE compression (default, good balance)
with zipfile.ZipFile('deflate.zip', 'w', zipfile.ZIP_DEFLATED) as zf:
    zf.write('file.txt')
 
# BZIP2 (better compression, slower)
with zipfile.ZipFile('bzip2.zip', 'w', zipfile.ZIP_BZIP2) as zf:
    zf.write('file.txt')
 
# LZMA (best compression, slowest)
with zipfile.ZipFile('lzma.zip', 'w', zipfile.ZIP_LZMA) as zf:
    zf.write('file.txt')
 
# Per-file compression
with zipfile.ZipFile('mixed.zip', 'w') as zf:
    zf.write('text.txt', compress_type=zipfile.ZIP_DEFLATED)
    zf.write('image.png', compress_type=zipfile.ZIP_STORED)

Password Protection

import zipfile
 
# Read password-protected ZIP
with zipfile.ZipFile('protected.zip', 'r') as zf:
    zf.extractall(pwd=b'secretpassword')
 
# Note: zipfile can READ encrypted zips but cannot CREATE them
# Use pyminizip or pyzipper for creating encrypted archives

Practical Examples

Backup Directory

import zipfile
import os
from datetime import datetime
 
def backup_directory(source_dir, backup_dir):
    timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
    zip_name = f"backup_{timestamp}.zip"
    zip_path = os.path.join(backup_dir, zip_name)
    
    with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zf:
        for root, dirs, files in os.walk(source_dir):
            for file in files:
                filepath = os.path.join(root, file)
                arcname = os.path.relpath(filepath, source_dir)
                zf.write(filepath, arcname)
    
    return zip_path
 
backup_directory('./project', './backups')

In-Memory ZIP

import zipfile
from io import BytesIO
 
# Create ZIP in memory
buffer = BytesIO()
with zipfile.ZipFile(buffer, 'w', zipfile.ZIP_DEFLATED) as zf:
    zf.writestr('file1.txt', 'Content 1')
    zf.writestr('file2.txt', 'Content 2')
 
# Get bytes for upload, response, etc.
zip_bytes = buffer.getvalue()

Extract with Progress

import zipfile
import os
 
def extract_with_progress(zip_path, extract_to):
    with zipfile.ZipFile(zip_path, 'r') as zf:
        members = zf.namelist()
        total = len(members)
        
        for i, member in enumerate(members, 1):
            zf.extract(member, extract_to)
            print(f"\rExtracting: {i}/{total}", end='')
        
        print("\nDone!")

Verify ZIP Integrity

import zipfile
 
def verify_zip(zip_path):
    try:
        with zipfile.ZipFile(zip_path, 'r') as zf:
            bad_file = zf.testzip()
            if bad_file:
                print(f"Corrupted file: {bad_file}")
                return False
            return True
    except zipfile.BadZipFile:
        print("Not a valid ZIP file")
        return False

Search in ZIP

import zipfile
import re
 
def search_in_zip(zip_path, pattern):
    matches = []
    regex = re.compile(pattern)
    
    with zipfile.ZipFile(zip_path, 'r') as zf:
        for name in zf.namelist():
            if name.endswith('/'):  # Skip directories
                continue
            try:
                content = zf.read(name).decode('utf-8')
                if regex.search(content):
                    matches.append(name)
            except UnicodeDecodeError:
                pass  # Skip binary files
    
    return matches

ZipInfo Object

import zipfile
from datetime import datetime
 
with zipfile.ZipFile('archive.zip', 'r') as zf:
    for info in zf.infolist():
        print(f"Name: {info.filename}")
        print(f"Size: {info.file_size}")
        print(f"Compressed: {info.compress_size}")
        print(f"Date: {datetime(*info.date_time)}")
        print(f"Is dir: {info.is_dir()}")
        print()

Quick Reference

import zipfile
 
# Open modes: 'r' read, 'w' write, 'a' append
with zipfile.ZipFile('file.zip', 'r') as zf:
    zf.namelist()           # List files
    zf.getinfo(name)        # Get ZipInfo
    zf.infolist()           # List ZipInfo objects
    zf.read(name)           # Read file bytes
    zf.extract(name, path)  # Extract one file
    zf.extractall(path)     # Extract all
    zf.testzip()            # Verify integrity
 
with zipfile.ZipFile('file.zip', 'w', zipfile.ZIP_DEFLATED) as zf:
    zf.write(filepath)              # Add file
    zf.write(filepath, arcname)     # Add with different name
    zf.writestr(name, data)         # Write string/bytes
CompressionConstantSpeedRatio
NoneZIP_STOREDFastest1:1
DeflateZIP_DEFLATEDFastGood
BZIP2ZIP_BZIP2SlowBetter
LZMAZIP_LZMASlowestBest

zipfile handles ZIP archives completely in Python. No need for system zip commands.

React to this post: