Python
File Handling
Unzipping
Data Compression
Programming Tutorial

Unzipping files in Python

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Python makes ZIP extraction straightforward with the standard-library zipfile module, so you usually do not need a third-party package just to unpack an archive. The basic API is simple, but production code should also think about path safety, destination handling, and whether you really want every file extracted.

Basic Extraction With zipfile

The most direct approach is to open the archive with ZipFile and call extractall().

python
1from pathlib import Path
2import zipfile
3
4zip_path = Path("data/archive.zip")
5out_dir = Path("data/unpacked")
6out_dir.mkdir(parents=True, exist_ok=True)
7
8with zipfile.ZipFile(zip_path, "r") as zf:
9    zf.extractall(out_dir)
10
11print(f"Extracted to {out_dir.resolve()}")

This works well for trusted archives and simple scripts. The context manager is important because it closes the ZIP file even if extraction fails.

If you only need to see what is inside before extracting, namelist() and infolist() are useful:

python
1import zipfile
2
3with zipfile.ZipFile("data/archive.zip", "r") as zf:
4    for info in zf.infolist():
5        print(info.filename, info.file_size)

That is a good first step if you want to inspect file names, sizes, or directory structure before writing anything to disk.

Extracting Specific Files

You do not always want the full archive. ZipFile.open() lets you read one member, and extract() lets you unpack a single named file.

python
1from pathlib import Path
2import zipfile
3
4with zipfile.ZipFile("data/archive.zip", "r") as zf:
5    zf.extract("reports/january.csv", path="data/single-file")
6
7path = Path("data/single-file/reports/january.csv")
8print(path.exists())

This is useful when archives are large and you only need a subset of files.

Safe Extraction To Avoid Path Traversal

The main security issue with ZIP extraction is path traversal, sometimes called Zip Slip. A malicious archive can contain names such as ../../etc/passwd and attempt to write outside your target directory.

For untrusted archives, validate each member before extracting it:

python
1from pathlib import Path
2import shutil
3import zipfile
4
5
6def safe_extract(zip_path: Path, destination: Path) -> None:
7    destination = destination.resolve()
8    destination.mkdir(parents=True, exist_ok=True)
9
10    with zipfile.ZipFile(zip_path, "r") as zf:
11        for member in zf.infolist():
12            target = (destination / member.filename).resolve()
13
14            if target != destination and not str(target).startswith(str(destination) + "/"):
15                raise ValueError(f"Unsafe path in archive: {member.filename}")
16
17            if member.is_dir():
18                target.mkdir(parents=True, exist_ok=True)
19                continue
20
21            target.parent.mkdir(parents=True, exist_ok=True)
22            with zf.open(member) as source, target.open("wb") as output:
23                shutil.copyfileobj(source, output)
24
25
26safe_extract(Path("data/archive.zip"), Path("data/safe-output"))

That extra logic is worth it any time the archive came from users, external vendors, or untrusted automation.

Handling Bad Or Corrupt Archives

zipfile raises BadZipFile when the archive is invalid. You can also call testzip() to check members before extraction.

python
1import zipfile
2
3try:
4    with zipfile.ZipFile("data/archive.zip", "r") as zf:
5        bad_member = zf.testzip()
6        if bad_member is not None:
7            raise ValueError(f"Corrupt entry: {bad_member}")
8        zf.extractall("data/validated-output")
9except zipfile.BadZipFile:
10    print("The file is not a valid ZIP archive.")

This is helpful in automation pipelines where you want a clear failure instead of half-extracted files.

Common Pitfalls

The most common mistake is assuming extractall() is always safe. It is convenient, but it should not be used blindly on untrusted archives.

Another pitfall is forgetting to create or resolve the destination path. Relative paths may put files somewhere unexpected when the script is run from a different working directory.

Large archives can also surprise you. A compressed ZIP file may expand to much more data on disk than its original file size suggests, so make sure you have enough storage before extraction.

Finally, do not forget that ZIP members can preserve nested directories. If later code expects a flat output directory, inspect the archive layout first instead of assuming file names will land at the top level.

Summary

  • Use Python's built-in zipfile module for most ZIP extraction tasks.
  • 'extractall() is fine for trusted archives and quick scripts.'
  • Inspect members with infolist() when you want more control.
  • Validate member paths for untrusted archives to prevent path traversal.
  • Handle corrupt archives explicitly with BadZipFile or testzip().

Course illustration
Course illustration

All Rights Reserved.