- What is file compression — saving space and organizing files
- zipfile module — Python's built-in ZIP tools
- Creating ZIP files — compressing your files
- Adding to ZIP — updating existing archives
- Extracting ZIP — unpacking compressed files
- Reading ZIP contents — exploring archives
What is File Compression?
Have you ever zipped a folder to send it by email? That's file compression in action. It's a way to reduce the size of files so they take up less space and are easier to share. Python's zipfile module lets you do this programmatically.
Think of compression like vacuum-packing clothes. The clothes take up less space and you can unpack them later when you need them. ZIP files work the same way — they pack your files into a smaller package that can be unpacked later.
💡 Key concept: ZIP files are archives that contain one or more files compressed to save space. They're widely used for backups, sharing, and organizing files. The zipfile module gives you full control over this process.
The zipfile Module
Python's Built-in ZIP Tools
# Python's zipfile module lets you work with ZIP archives
import zipfile
import os
# Creating sample files
with open("file1.txt", "w") as f:
f.write("This is file 1")
with open("file2.txt", "w") as f:
f.write("This is file 2")
with open("file3.txt", "w") as f:
f.write("This is file 3")
# 1. Check if a file is a ZIP archive
def is_zip_file(filename):
"""Check if a file is a ZIP archive"""
return zipfile.is_zipfile(filename)
# 2. Creating a simple ZIP file
print("Creating a ZIP file...")
with zipfile.ZipFile("simple.zip", "w") as zipf:
zipf.write("file1.txt")
zipf.write("file2.txt")
print("Created: simple.zip")
# 3. Check if it's a ZIP file
print(f"Is simple.zip a ZIP file? {is_zip_file('simple.zip')}")
print(f"Is file1.txt a ZIP file? {is_zip_file('file1.txt')}")
# 4. List contents of a ZIP file
with zipfile.ZipFile("simple.zip", "r") as zipf:
print(f"Contents of simple.zip:")
for filename in zipf.namelist():
print(f" {filename}")
zipfile module key points:
- Built-in — no installation needed
- Read and write — create and extract archives
- List contents — see what's inside a ZIP
- Check validity — verify if a file is a ZIP
Quick Check: What module is used to work with ZIP files in Python? (Answer: zipfile)
Creating ZIP Files
Compressing Your Files
# Creating ZIP files with the zipfile module
import zipfile
import os
# 1. Create a ZIP file with multiple files
def create_zip(zip_name, file_list):
"""Create a ZIP file from a list of files"""
with zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED) as zipf:
for file in file_list:
if os.path.exists(file):
zipf.write(file)
print(f" Added: {file}")
else:
print(f" Warning: {file} not found")
print(f"Created: {zip_name}")
# 2. Create ZIP with compression
def create_compressed_zip(zip_name, file_list, compression=zipfile.ZIP_DEFLATED):
"""Create a ZIP with specified compression"""
with zipfile.ZipFile(zip_name, 'w', compression) as zipf:
for file in file_list:
zipf.write(file)
print(f"Created compressed ZIP: {zip_name}")
# 3. Create ZIP with a different name inside
def create_zip_with_rename(zip_name):
"""Create a ZIP with renamed files inside"""
with zipfile.ZipFile(zip_name, 'w') as zipf:
zipf.write("file1.txt", "renamed1.txt")
zipf.write("file2.txt", "renamed2.txt")
print(f"Created ZIP with renamed files: {zip_name}")
# 4. Create ZIP from a directory
def zip_directory(directory, zip_name):
"""Create a ZIP of an entire directory"""
with zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED) as zipf:
for root, dirs, files in os.walk(directory):
for file in files:
full_path = os.path.join(root, file)
arcname = os.path.relpath(full_path, start=os.path.dirname(directory))
zipf.write(full_path, arcname)
print(f"Zipped directory: {directory} → {zip_name}")
# Let's create some files to zip
for i in range(5):
with open(f"doc_{i}.txt", "w") as f:
f.write(f"Document {i}")
# Create a ZIP
create_zip("documents.zip", ["doc_0.txt", "doc_1.txt", "doc_2.txt"])
# Create a compressed ZIP
create_compressed_zip("compressed.zip", ["doc_3.txt", "doc_4.txt"])
# Create ZIP with renamed files
create_zip_with_rename("renamed.zip")
# Create a directory and zip it
os.makedirs("project", exist_ok=True)
with open("project/data.txt", "w") as f:
f.write("Project data")
with open("project/notes.txt", "w") as f:
f.write("Project notes")
zip_directory("project", "project.zip")
Creating ZIP files key points:
- 'w' mode — write/create a new ZIP
- ZIP_DEFLATED — compression method
- Add files — use write() method
- Rename inside — specify different name in archive
- Directory support — can zip entire folders
Quick Check: What mode is used to create a new ZIP file? (Answer: 'w')
Adding Files to a ZIP
Updating Existing Archives
# Adding files to an existing ZIP archive
import zipfile
import os
# Create a ZIP with one file
with zipfile.ZipFile("update.zip", "w") as zipf:
zipf.write("doc_0.txt")
print("Created: update.zip")
# 1. Add a file to an existing ZIP
def add_to_zip(zip_name, file_to_add):
"""Add a file to an existing ZIP"""
with zipfile.ZipFile(zip_name, 'a') as zipf:
zipf.write(file_to_add)
print(f"Added {file_to_add} to {zip_name}")
add_to_zip("update.zip", "doc_1.txt")
add_to_zip("update.zip", "doc_2.txt")
# 2. Add multiple files
def add_multiple_to_zip(zip_name, file_list):
"""Add multiple files to a ZIP"""
with zipfile.ZipFile(zip_name, 'a') as zipf:
for file in file_list:
zipf.write(file)
print(f" Added: {file}")
add_multiple_to_zip("update.zip", ["doc_3.txt", "doc_4.txt"])
# 3. Check what's in the ZIP
with zipfile.ZipFile("update.zip", "r") as zipf:
print(f"Contents of update.zip:")
for filename in zipf.namelist():
print(f" {filename}")
# 4. Add a file with a different name
def add_file_with_new_name(zip_name, file, new_name):
"""Add a file with a new name inside the ZIP"""
with zipfile.ZipFile(zip_name, 'a') as zipf:
zipf.write(file, new_name)
print(f"Added {file} as {new_name} in {zip_name}")
add_file_with_new_name("update.zip", "doc_4.txt", "final_doc.txt")
# 5. Add files from a directory
def add_directory_to_zip(zip_name, directory):
"""Add all files from a directory to an existing ZIP"""
with zipfile.ZipFile(zip_name, 'a') as zipf:
for root, dirs, files in os.walk(directory):
for file in files:
full_path = os.path.join(root, file)
arcname = os.path.relpath(full_path)
zipf.write(full_path, arcname)
print(f" Added: {arcname}")
# 6. 'a' mode for appending
# Important: You can only add to ZIPs, not remove or modify existing files
Adding to ZIP key points:
- 'a' mode — append to existing ZIP
- Add files — same write() method
- Rename inside — specify new name
- Add directories — walk and add all files
- Cannot remove — only add new files
Quick Check: What mode is used to add files to an existing ZIP? (Answer: 'a')
Extracting ZIP Files
Unpacking Compressed Files
# Extracting files from a ZIP archive
import zipfile
import os
# 1. Extract all files
def extract_all(zip_name, extract_to="extracted"):
"""Extract all files from a ZIP"""
os.makedirs(extract_to, exist_ok=True)
with zipfile.ZipFile(zip_name, 'r') as zipf:
zipf.extractall(extract_to)
print(f"Extracted all files from {zip_name} to {extract_to}")
# 2. Extract specific files
def extract_specific(zip_name, files_to_extract, extract_to="."):
"""Extract specific files from a ZIP"""
with zipfile.ZipFile(zip_name, 'r') as zipf:
for file in files_to_extract:
zipf.extract(file, extract_to)
print(f" Extracted: {file}")
# 3. Extract a single file
def extract_file(zip_name, file_name, extract_to="."):
"""Extract a single file from a ZIP"""
with zipfile.ZipFile(zip_name, 'r') as zipf:
zipf.extract(file_name, extract_to)
print(f"Extracted: {file_name} from {zip_name}")
# 4. Extract with progress
def extract_with_progress(zip_name, extract_to="extracted"):
"""Extract with progress indication"""
with zipfile.ZipFile(zip_name, 'r') as zipf:
files = zipf.namelist()
total = len(files)
print(f"Extracting {total} files...")
for i, file in enumerate(files, 1):
zipf.extract(file, extract_to)
print(f" Progress: {i}/{total} - {file}")
print("Extraction complete!")
# 5. Extract to a specific directory
def extract_to_directory(zip_name, target_dir):
"""Extract ZIP to a specific directory"""
os.makedirs(target_dir, exist_ok=True)
with zipfile.ZipFile(zip_name, 'r') as zipf:
zipf.extractall(target_dir)
print(f"Extracted to: {target_dir}")
# Let's create a sample ZIP first
with zipfile.ZipFile("sample_extract.zip", "w") as zipf:
zipf.write("doc_0.txt")
zipf.write("doc_1.txt")
zipf.write("doc_2.txt")
zipf.write("doc_3.txt")
# Test the extraction functions
extract_all("sample_extract.zip")
extract_specific("sample_extract.zip", ["doc_0.txt", "doc_2.txt"])
extract_file("sample_extract.zip", "doc_1.txt")
extract_to_directory("sample_extract.zip", "my_extracted_files")
Extracting key points:
- extractall() — extract everything
- extract() — extract specific files
- 'r' mode — read the ZIP file
- Target directory — choose where to extract
- Progress tracking — monitor extraction
Quick Check: What method extracts all files from a ZIP? (Answer: extractall())
Reading ZIP Contents
Exploring Archives Without Extracting
# Reading ZIP contents without extracting
import zipfile
import os
# 1. Get list of files
def list_zip_contents(zip_name):
"""List all files in a ZIP"""
with zipfile.ZipFile(zip_name, 'r') as zipf:
print(f"Contents of {zip_name}:")
for info in zipf.infolist():
print(f" {info.filename} - {info.file_size} bytes")
# 2. Get file information
def get_file_info(zip_name, file_name):
"""Get information about a specific file in a ZIP"""
with zipfile.ZipFile(zip_name, 'r') as zipf:
info = zipf.getinfo(file_name)
print(f"File: {info.filename}")
print(f" Size: {info.file_size} bytes")
print(f" Compressed: {info.compress_size} bytes")
print(f" Compression ratio: {info.compress_size / info.file_size * 100:.1f}%")
# 3. Read a file from ZIP without extracting
def read_file_from_zip(zip_name, file_name):
"""Read the content of a file inside a ZIP"""
with zipfile.ZipFile(zip_name, 'r') as zipf:
content = zipf.read(file_name)
return content
# 4. Search for files in a ZIP
def search_in_zip(zip_name, pattern):
"""Search for files matching a pattern in a ZIP"""
with zipfile.ZipFile(zip_name, 'r') as zipf:
matches = []
for filename in zipf.namelist():
if pattern in filename:
matches.append(filename)
return matches
# 5. Get ZIP file statistics
def get_zip_stats(zip_name):
"""Get statistics about a ZIP file"""
with zipfile.ZipFile(zip_name, 'r') as zipf:
total_files = len(zipf.namelist())
total_size = sum(info.file_size for info in zipf.infolist())
total_compressed = sum(info.compress_size for info in zipf.infolist())
print(f"ZIP: {zip_name}")
print(f" Total files: {total_files}")
print(f" Total size: {total_size} bytes")
print(f" Compressed size: {total_compressed} bytes")
print(f" Savings: {total_size - total_compressed} bytes")
# 6. Check if a file exists in a ZIP
def file_exists_in_zip(zip_name, file_name):
"""Check if a file exists in a ZIP"""
with zipfile.ZipFile(zip_name, 'r') as zipf:
return file_name in zipf.namelist()
# Create a sample ZIP
with zipfile.ZipFile("read_sample.zip", "w") as zipf:
zipf.write("doc_0.txt")
zipf.write("doc_1.txt")
zipf.write("doc_2.txt")
# Test the functions
list_zip_contents("read_sample.zip")
get_file_info("read_sample.zip", "doc_0.txt")
# Read a file from the ZIP
content = read_file_from_zip("read_sample.zip", "doc_0.txt")
print(f"Content of doc_0.txt: {content.decode()}")
# Search for files
matches = search_in_zip("read_sample.zip", "doc")
print(f"Files containing 'doc': {matches}")
# Get statistics
get_zip_stats("read_sample.zip")
Reading ZIP key points:
- namelist() — list of file names
- infolist() — detailed information
- read() — read file content without extracting
- getinfo() — get specific file info
- Statistics — analyze ZIP contents
Quick Check: How do you read a file from a ZIP without extracting it? (Answer: Use the read() method)
Error Handling with ZIP Files
Robust ZIP Operations
# Handling errors when working with ZIP files
import zipfile
import os
# 1. Safe ZIP creation
def safe_create_zip(zip_name, file_list):
"""Safely create a ZIP file"""
try:
with zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED) as zipf:
for file in file_list:
if os.path.exists(file) and os.path.isfile(file):
zipf.write(file)
else:
print(f"Warning: {file} not found or not a file")
return True
except PermissionError:
print(f"Permission denied: Cannot create {zip_name}")
return False
except Exception as e:
print(f"Error creating ZIP: {e}")
return False
# 2. Safe ZIP extraction
def safe_extract_zip(zip_name, extract_to="extracted"):
"""Safely extract a ZIP file"""
try:
if not zipfile.is_zipfile(zip_name):
print(f"Error: {zip_name} is not a valid ZIP file")
return False
os.makedirs(extract_to, exist_ok=True)
with zipfile.ZipFile(zip_name, 'r') as zipf:
zipf.extractall(extract_to)
return True
except PermissionError:
print(f"Permission denied: Cannot extract to {extract_to}")
return False
except zipfile.BadZipFile:
print(f"Error: {zip_name} is corrupted or not a ZIP file")
return False
except Exception as e:
print(f"Error extracting ZIP: {e}")
return False
# 3. Safe file addition
def safe_add_to_zip(zip_name, file_to_add):
"""Safely add a file to a ZIP"""
try:
if not zipfile.is_zipfile(zip_name):
print(f"Error: {zip_name} is not a valid ZIP file")
return False
if not os.path.exists(file_to_add):
print(f"Error: {file_to_add} does not exist")
return False
with zipfile.ZipFile(zip_name, 'a') as zipf:
zipf.write(file_to_add)
return True
except Exception as e:
print(f"Error adding to ZIP: {e}")
return False
# 4. Safe ZIP info reading
def safe_read_zip_info(zip_name):
"""Safely read ZIP information"""
try:
if not zipfile.is_zipfile(zip_name):
print(f"Error: {zip_name} is not a valid ZIP file")
return None
with zipfile.ZipFile(zip_name, 'r') as zipf:
return zipf.namelist()
except Exception as e:
print(f"Error reading ZIP: {e}")
return None
Error handling key points:
- BadZipFile — corrupted or invalid ZIP
- PermissionError — can't access files
- Check validity — use is_zipfile()
- Check existence — verify files exist
- Always handle errors — make code robust
Quick Check: What exception is raised for a corrupted ZIP file? (Answer: BadZipFile)
Best Practices for ZIP Files
Professional ZIP File Handling
# Best practices for working with ZIP files
import zipfile
import os
# 1. Use context managers
# ✅ Good
with zipfile.ZipFile("archive.zip", "w") as zipf:
zipf.write("file.txt")
# ❌ Bad
# zipf = zipfile.ZipFile("archive.zip", "w")
# zipf.write("file.txt")
# zipf.close() # Might be forgotten
# 2. Use compression
# ✅ Good - saves space
with zipfile.ZipFile("compressed.zip", "w", zipfile.ZIP_DEFLATED) as zipf:
zipf.write("file.txt")
# 3. Check if files exist before adding
def add_file_safely(zipf, file_path, arcname=None):
"""Add a file only if it exists"""
if os.path.exists(file_path) and os.path.isfile(file_path):
zipf.write(file_path, arcname)
return True
return False
# 4. Use meaningful names inside ZIP
with zipfile.ZipFile("archive.zip", "w") as zipf:
zipf.write("original_name.txt", "clean_name.txt")
# 5. Handle large files carefully
def create_zip_with_progress(zip_name, file_list):
"""Create a ZIP with progress reporting"""
total = len(file_list)
with zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED) as zipf:
for i, file_path in enumerate(file_list, 1):
if os.path.exists(file_path):
zipf.write(file_path)
print(f"Added {i}/{total}: {file_path}")
else:
print(f"Warning: {file_path} not found")
# 6. Verify ZIP integrity
def verify_zip(zip_name):
"""Verify a ZIP file's integrity"""
try:
with zipfile.ZipFile(zip_name, 'r') as zipf:
# Test reading all files
for file in zipf.namelist():
zipf.read(file)
return True
except Exception:
return False
# 7. Extract safely (avoid path traversal)
def safe_extract(zip_name, extract_to="extracted"):
"""Extract safely without path traversal"""
with zipfile.ZipFile(zip_name, 'r') as zipf:
for member in zipf.namelist():
# Prevent path traversal attacks
if member.startswith('/') or '..' in member:
print(f"Warning: Skipping potentially unsafe file: {member}")
continue
zipf.extract(member, extract_to)
# 8. Clean up temporary files
# Always remove temporary ZIP files when done
# os.remove("temp.zip")
Best practices summary:
- Use context managers — automatic closing
- Use compression — save space with ZIP_DEFLATED
- Check existence — verify files before adding
- Use meaningful names — organize inside ZIP
- Verify integrity — test ZIP files
- Extract safely — prevent path traversal
Quick Check: What compression method should you use? (Answer: ZIP_DEFLATED)
Try It Yourself
Experiment with zipping and unzipping files in the editor below.
ZIPPING AND UNZIPPING PRACTICE
========================================
1. CREATING SAMPLE FILES
Created: sample1.txt, sample2.txt, sample3.txt
2. CREATING A ZIP FILE
Created: my_archive.zip
3. LISTING ZIP CONTENTS
Files in archive:
sample1.txt
sample2.txt
sample3.txt
4. EXTRACTING ZIP FILE
Extracted to: extracted_files/
5. READING FROM ZIP
sample1.txt content: This is sample file 1
6. ADDING TO EXISTING ZIP
Added sample4.txt to my_archive.zip
Zipping and unzipping practice complete!
You've Got It!
You now know how to work with ZIP files in Python. You can create, add to, extract, and read ZIP archives.
Quick Quiz
Test what you've learned:
Frequently Asked Questions
What is the difference between ZIP_STORED and ZIP_DEFLATED?
Can I add files to an existing ZIP without extracting?
'a' mode (append) with ZipFile. You can add new files without extracting the entire archive: with zipfile.ZipFile("archive.zip", "a") as zipf: zipf.write("new_file.txt").
How do I check if a file is a valid ZIP?
zipfile.is_zipfile(filename). It returns True if the file appears to be a valid ZIP archive. This is a quick way to check before trying to open it.
What's a common interview question about ZIP files?
Can I read a file from a ZIP without extracting it?
read() method: content = zipf.read("file.txt"). This returns the file content as bytes without creating a physical file on disk.
How do I zip an entire directory?
os.walk() to traverse the directory and add each file to the ZIP. Use os.path.relpath() to preserve the directory structure inside the ZIP.
Where to Go From Here
Now that you can work with ZIP files, check out these related topics:
📝 Assignments
Practice what you've learned with assignments.
Learn More →MySQL Database
Learn how to work with databases in Python.
Learn More →Object-Oriented Programming
Learn about classes and objects in Python.
Learn More →