Python Basics: Creating and Inspecting ZIP Archives
Python’s standard-library zipfile module can create a ZIP archive, list its members, and read a selected file without extracting it.
Use Python 3.12 or newer on Linux. The example creates its own small files in a fresh temporary directory. Warning: leaving the TemporaryDirectory context removes that directory and everything inside it.
Create an archive and read it back
Save as demo_zipfile_1.py:
from pathlib import Path
from tempfile import TemporaryDirectory
from zipfile import ZipFile, ZIP_DEFLATED
with TemporaryDirectory() as directory:
workspace = Path(directory)
source = workspace / "notes.txt"
archive = workspace / "bundle.zip"
with source.open("x", encoding="utf-8") as file:
file.write("Ready for review\n")
with ZipFile(archive, "x", compression=ZIP_DEFLATED) as bundle:
bundle.write(source, arcname="notes.txt")
bundle.writestr("status.txt", "draft\n")
with ZipFile(archive, "r") as bundle:
for member in bundle.infolist():
print(member.filename, member.file_size)
print(bundle.read("notes.txt").decode("utf-8"), end="")
print("CRC check:", bundle.testzip())Run:
python3 demo_zipfile_1.pyOutput:
notes.txt 17
status.txt 6
Ready for review
CRC check: NoneMode "x" creates an archive exclusively and raises FileExistsError if it already exists. Mode "w" would replace an existing archive. arcname controls the path stored inside the ZIP, so the temporary directory name is not included.
ZIP_DEFLATED uses compression and requires Python’s zlib support. file_size is the uncompressed size. The context manager closes the writer before the archive is reopened for reading.
Handle an absent member
read() returns bytes and raises KeyError for a missing name. This independent example keeps the archive in memory.
Save as demo_zipfile_2.py:
from io import BytesIO
from zipfile import ZipFile
with BytesIO() as buffer:
with ZipFile(buffer, "w") as bundle:
bundle.writestr("status.txt", "draft\n")
buffer.seek(0)
with ZipFile(buffer, "r") as bundle:
try:
bundle.read("missing.txt")
except KeyError:
print("Member not found")Run:
python3 demo_zipfile_2.pyOutput:
Member not foundtestzip() reads all members and returns the first name with a bad CRC or header, or None when it finds none. This checks corruption, not authenticity.
Only use these unrestricted reads on small, trusted archives. Compressed content can expand dramatically, and read() loads a whole member into memory. For outside archives, enforce size and resource limits and review member paths before any extraction. Listing names alone does not make extraction safe.
References
Acknowledgements
This post was created with assistance from AI.