Skip to content
Foxipa

Suggest an edit

Tell us what should be corrected, clarified, or improved. Submission will be connected to Foxipa’s contribution service later.

No information is sent anywhere yet. Your suggestion is only prepared in your browser.

Learning

Working with TAR Archives Using tarfile

Create, inspect, read, compress, and cautiously extract TAR archives with Python’s standard-library tarfile module.

Levels: Intermediate ~40 min read

Intermediate

Python’s tarfile module reads and writes TAR archives. Unlike a ZIP archive, a TAR archive is fundamentally a sequence of filesystem entries; compression is a separate choice such as gzip or xz. Use tarfile when you need direct control over archive members, metadata, streaming, or extraction filters. Use shutil for simpler whole-directory archive workflows, and zipfile for ZIP members.

Choose a TAR mode and compression method

The first part of a mode describes the operation: “r” reads, “w” creates or replaces, “x” creates only if the path does not already exist, and “a” appends. Add a compression suffix such as “:gz” or “:xz” when creating a compressed TAR archive. “r:*” reads a supported TAR archive and detects its compression. Appending is supported only for uncompressed TAR files; modes such as “a:gz” are not valid.

Interactive Runnable example
Edit

Ready to run.

Add in-memory content with TarInfo and addfile

When the content already exists as bytes instead of a filesystem file, create a TarInfo entry, set its size to the byte count, and pass a binary file-like object to addfile(). This avoids writing a temporary source file first. The member name is still the name stored inside the archive, not a destination path on the current computer.

Interactive Runnable example
Edit

Ready to run.

Create a compressed TAR archive

A mode like “w:gz” creates a gzip-compressed TAR archive. Compression happens around the TAR stream; it does not turn the archive into a ZIP file. tarfile.open(path, “r:*”) transparently reads supported compressed and uncompressed TAR formats. Python 3.14 added optional Zstandard support through compression.zstd; the local examples below intentionally use gzip because it is available in Python 3.13 as well.

Interactive Runnable example
Edit

Ready to run.

Inspect TarInfo members

getmembers() returns TarInfo objects in archive order. Each member exposes information such as name, size, and file type. Check isfile(), isdir(), or issym() before treating an entry as a regular file: TAR archives can represent directories and links as well as file content. An archive can also contain more than one entry with the same name.

Interactive Runnable example
Edit

Ready to run.

Read a member without extracting the archive

extractfile() returns a binary file-like object for a regular file or supported link, or None for directory entries. Read and decode the returned bytes using the encoding of the stored text. This lets you inspect a single member without writing the entire archive to disk, but still treat the archive and its declared sizes as untrusted input.

Interactive Runnable example
Edit

Ready to run.

Extract into a controlled directory with a data filter

When extracting archives that are not fully trusted, inspect them first and pass filter="data" explicitly where supported. The data filter rejects many risky paths, links, and special files. It is not a complete security guarantee: an archive can still exhaust disk, memory, or CPU, and the destination can be affected by filesystem races. Prefer a new temporary destination and impose application-specific limits. The default filter changed in Python 3.14, so explicit selection makes the intended policy clear on supported versions. Python 3.15 further normalizes names containing `..` in the built-in tar filter and link targets containing `..` in the data filter; older runtimes may behave differently, so do not treat version-specific normalization as a substitute for inspecting members.

Interactive Runnable example
Edit

Ready to run.

Understand why the extraction filter matters

A TAR member name such as “../outside.txt” attempts to escape its intended destination. Do not hand untrusted archives to fully_trusted extraction, and do not assume a filter eliminates every risk. The following example creates a harmless test archive containing a traversal-style name and verifies that the data filter rejects it without creating the outside file. For real untrusted archives, inspect members before extraction and consider limits on member count, per-file size, total expanded size, and accepted names.

Interactive Runnable example
Edit

Ready to run.

Keep practising

Store a file under a portable member name

Which expression adds the existing file under the desired archive-relative name?

from pathlib import Path
from tempfile import TemporaryDirectory
import tarfile

with TemporaryDirectory() as folder:
    root = Path(folder)
    source = root / "today.txt"
    source.write_text("Today", encoding="utf-8")
    archive_path = root / "today.tar"
    with tarfile.open(archive_path, "w") as archive:
        
    with tarfile.open(archive_path) as archive:
        assert archive.getnames() == ["reports/today.txt"]
    print("portable member name stored")

Choose gzip compression

Which mode creates a gzip-compressed TAR archive?

from pathlib import Path
from tempfile import TemporaryDirectory
import tarfile

with TemporaryDirectory() as folder:
    root = Path(folder)
    source = root / "notes.txt"
    source.write_text("Notes", encoding="utf-8")
    archive_path = root / "notes.tar.gz"
    with tarfile.open(archive_path, ) as archive:
        archive.add(source, arcname="notes.txt")
    with tarfile.open(archive_path, "r:*") as archive:
        assert archive.getnames() == ["notes.txt"]
    print("gzip TAR read")

Inspect member size

Which object provides the name, size, and isfile() method for one archive member?

from pathlib import Path
from tempfile import TemporaryDirectory
import tarfile

with TemporaryDirectory() as folder:
    root = Path(folder)
    source = root / "brief.txt"
    source.write_text("Short brief", encoding="utf-8")
    archive_path = root / "brief.tar"
    with tarfile.open(archive_path, "w") as archive:
        archive.add(source, arcname="brief.txt")
    with tarfile.open(archive_path) as archive:
        member = archive.getmembers()[0]
        print(member.)
        assert member.size == len("Short brief")
    print("metadata checked")

Read without extracting

Which method opens a single member for reading without extracting it to a filesystem path?

from pathlib import Path
from tempfile import TemporaryDirectory
import tarfile

with TemporaryDirectory() as folder:
    root = Path(folder)
    source = root / "notes.txt"
    source.write_text("Archive note", encoding="utf-8")
    archive_path = root / "notes.tar"
    with tarfile.open(archive_path, "w") as archive:
        archive.add(source, arcname="notes.txt")
    with tarfile.open(archive_path) as archive:
        with archive.("notes.txt") as stream:
            contents = stream.read()
    assert contents == b"Archive note"
    print("read without extraction")

Apply the data extraction filter

Which argument selects the data extraction policy explicitly?

from pathlib import Path
from tempfile import TemporaryDirectory
import tarfile

with TemporaryDirectory() as folder:
    root = Path(folder)
    source = root / "notes.txt"
    source.write_text("Safe note", encoding="utf-8")
    archive_path = root / "notes.tar"
    with tarfile.open(archive_path, "w") as archive:
        archive.add(source, arcname="notes.txt")
    destination = root / "out"
    destination.mkdir()
    with tarfile.open(archive_path) as archive:
        archive.extractall(path=destination, )
    assert (destination / "notes.txt").read_text(encoding="utf-8") == "Safe note"
    print("controlled extraction complete")
Was this page helpful?

Mark this learning resource complete to track your learning progress.