Skip to main content

A high level archive handler for Python.

Project description

multiarchive

A high level abstraction of multiple archive formats

Installation

uv add multiarchive

Optional dependency for RAR support:

uv add rarfile

ZStandard support requires the backports-zstd package on Python <3.14:

uv add "backports-zstd; python_version < '3.14'"

Quick Start

from multiarchive import Archive

# Open and inspect
with Archive("archive.zip") as arc:
    print(arc.namelist())  # list of member names
    print(len(arc))        # number of members
    print(arc.size)        # total uncompressed size in bytes

# Extract a single file
with Archive("archive.tar.gz") as arc:
    arc.extract("docs/readme.md", path="./output")

# Read file contents without extracting
with Archive("archive.zip") as arc:
    f = arc.open("config.json")
    content = f.read()
    f.close()

# Iterate over members
with Archive("archive.zip") as arc:
    for name in arc:
        if arc.is_file(name):
            print(f"  {name}")

Supported Formats

Format Read Write Extensions
ZIP Yes Yes .zip
TAR Yes Yes .tar
TAR.GZ Yes Yes .tgz, .tar.gz
TAR.BZ2 Yes Yes .tbz, .tbz2, .tar.bz2
TAR.XZ Yes Yes .tar.xz, .tar.lzma
TAR.ZST Yes Yes .tzst, .tar.zst
RAR Yes No .rar

RAR support requires the rarfile package and an external unrar tool.

Reading Archives

Opening

Use the context manager (recommended):

with Archive("file.zip") as arc:
    ...

Or the classmethod:

arc = Archive.open_archive("file.zip")
try:
    arc.namelist()
finally:
    arc.close()

Reading is supported on all formats, but password-protected archives are not supported and will raise a ValueError. If algo isnt explicitly provided, it will attempt to open it as ZIP first, then TAR, then RAR (if rarfile is installed). If all fails, it raises a ValueError.

Listing Members

with Archive("file.zip") as arc:
    names = arc.namelist()  # Just names
    names = arc.members     # alias to namelist

    # extra info (ArchiveMemberInfo objects)
    for info in arc.infolist():
        print(f"{info.name}: {info.uncompressed_size} bytes, mtime={info.mtime}")

Checking Membership

with Archive("file.zip") as arc:
    if "config.json" in arc:
        print("Found!")

    for name in arc:
        if arc.is_file(name):
            ...
        if arc.is_dir(name):
            ...

Extracting

with Archive("file.tar.gz") as arc:
    # Single file
    arc.extract("src/main.py", path="./extracted")

Reading Member Contents

with Archive("file.zip") as arc:
    f = arc.open("data.json")
    if f is not None:
        content = f.read()
        f.close()

Writing Archives

Creating a New Archive

from multiarchive import Archive

# ZIP
with Archive("output.zip", mode="w") as arc:
    ...

# TAR.GZ with compression level
with Archive("output.tar.gz", mode="w", compression_level=9) as arc:
    ...

The format is determined by file extension. Use the algo parameter to override:

with Archive("my_archive", mode="w", algo="tar.xz") as arc:
    ...

Compression Levels

Format Range Default
ZIP 0–9 6
TAR.GZ 0–9 6
TAR.BZ2 1–9 9
TAR.XZ 0–9 6
TAR.ZST 1–22 3

File Information Object

The infolist() method returns ArchiveMemberInfo objects with a unified interface across all formats:

Field Type Description
name str Member filename
uncompressed_size int Original file size in bytes
compressed_size int | None Compressed size (None for TAR)
mtime float Modification time as epoch seconds
mode int | None Unix permission bits
is_dir bool Whether the member is a directory
raw ZipInfo | TarInfo | RarInfo Original backend object (escape hatch)

Factory methods for direct conversion (you shouldn't need these in normal usage):

info = ArchiveMemberInfo.from_zipinfo(zip_info)
info = ArchiveMemberInfo.from_tarinfo(tar_info)
info = ArchiveMemberInfo.from_rarinfo(rar_info)

Properties

Method/Property Description
members Alias for namelist()
size Total uncompressed size of all members
comment / comment= Get/set archive comment (ZIP only, raises ValueError otherwise)

Error Handling

from multiarchive import Archive, BadArchiveError

try:
    with Archive("corrupted.zip") as arc:
        arc.namelist()
except BadArchiveError as e:
    print(f"Archive error: {e}")
except NotImplementedError as e:
    # password-protected (not supported)
    print(f"Not implemented: {e}")
except ValueError as e:
    # Unknown format
    print(f"Value error: {e}")
except FileNotFoundError:
    print("File not found")

API Reference

Archive

Archive(
    filename: str | Path,
    mode: str = "r",
    compression_level: int | None = None,
)
Parameter Description
filename Path to the archive file
mode 'r' for read, 'w' for write, 'a' for append
compression_level Compression level (format-dependent)

Methods

Method Description
open_archive(cls, filename, mode, compression_level) Factory method, returns opened archive
namelist() List of member names
infolist() List of ArchiveMemberInfo objects
extract(member, path) Extract single member
open(member, mode) Open member as file-like object
is_dir(member) Check if member is a directory
is_file(member) Check if member is a file
close() Explicitly close the archive

BadArchiveError

Raised when an archive file is corrupt or in an unsupported format.

ArchiveExtensions

Frozen dataclass mapping format names to their common file extensions:

ArchiveExtensions.zip     # (".zip",)
ArchiveExtensions.gz      # (".tgz", ".tar.gz")
ArchiveExtensions.xz      # (".tar.xz", ".tar.lzma")
# ... etc

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

multiarchive-0.1.0.tar.gz (8.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

multiarchive-0.1.0-py3-none-any.whl (8.8 kB view details)

Uploaded Python 3

File details

Details for the file multiarchive-0.1.0.tar.gz.

File metadata

  • Download URL: multiarchive-0.1.0.tar.gz
  • Upload date:
  • Size: 8.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for multiarchive-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d43f13a081e3b8d8c716c032436be070e1898f751efb089ce9a935779ae2b84d
MD5 46756d12c1beac2d17f497b1b33e4a74
BLAKE2b-256 dd9f08b9b570f402cd69c69c435f6a835b31756159da5bdca36bd50b41411ae1

See more details on using hashes here.

File details

Details for the file multiarchive-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: multiarchive-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 8.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for multiarchive-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0a99a06a4f9502f599f3701184c25a2144afaee35c53578ca8e63f1c89377055
MD5 c753bf4ecf9daa94585d096ea166361c
BLAKE2b-256 c7c43ec0a40052f944ae9ee7b9eeefcc240c28745489d957dda10055bed8775e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page