Welcome to zipp documentation!

For Enterprise

Professional support for zipp is available as part of the Tidelift Subscription. Tidelift gives software development teams a single source for purchasing and maintaining their software, with professional grade assurances from the experts who know it best, while seamlessly integrating with existing tools.

Learn more Request a Demo

A Path-like interface for zipfiles.

This codebase is shared between zipfile.Path in the stdlib and zipp in PyPI. See https://github.com/python/importlib_metadata/wiki/Development-Methodology for more detail.

class zipp.Path(root, at='')

Bases: object

A importlib.resources.abc.Traversable interface for zip files.

Implements many of the features users enjoy from pathlib.Path.

Consider a zip file with this structure:

.
├── a.txt
└── b
    ├── c.txt
    └── d
        └── e.txt
>>> data = io.BytesIO()
>>> zf = zipfile.ZipFile(data, 'w')
>>> zf.writestr('a.txt', 'content of a')
>>> zf.writestr('b/c.txt', 'content of c')
>>> zf.writestr('b/d/e.txt', 'content of e')
>>> zf.filename = 'mem/abcde.zip'

Path accepts the zipfile object itself or a filename

>>> path = Path(zf)

From there, several path operations are available.

Directory iteration (including the zip file itself):

>>> a, b = path.iterdir()
>>> a
Path('mem/abcde.zip', 'a.txt')
>>> b
Path('mem/abcde.zip', 'b/')

name property:

>>> b.name
'b'

join with divide operator:

>>> c = b / 'c.txt'
>>> c
Path('mem/abcde.zip', 'b/c.txt')
>>> c.name
'c.txt'

Read text:

>>> c.read_text(encoding='utf-8')
'content of c'

existence:

>>> c.exists()
True
>>> (b / 'missing.txt').exists()
False

Coercion to string:

>>> import os
>>> str(c).replace(os.sep, posixpath.sep)
'mem/abcde.zip/b/c.txt'

At the root, name, filename, and parent resolve to the zipfile.

>>> str(path)
'mem/abcde.zip/'
>>> path.name
'abcde.zip'
>>> path.filename == pathlib.Path('mem/abcde.zip')
True
>>> str(path.parent)
'mem'

If the zipfile has no filename, such attributes are not valid and accessing them will raise an Exception.

>>> zf.filename = None
>>> path.name
Traceback (most recent call last):
...
TypeError: ...
>>> path.filename
Traceback (most recent call last):
...
TypeError: ...
>>> path.parent
Traceback (most recent call last):
...
TypeError: ...

# workaround python/cpython#106763 >>> pass

exists()
property filename
glob(pattern)
is_dir()
is_file()

Return whether this path is a symlink.

iterdir()
joinpath(*other)
match(path_pattern)
property name
open(mode='r', *args, pwd=None, **kwargs)

Open this entry as text or binary following the semantics of pathlib.Path.open() by passing arguments through to io.TextIOWrapper().

property parent
read_bytes()
read_text(*args, **kwargs)
relative_to(other, *extra)
rglob(pattern)
property stem
property suffix
property suffixes
class zipp.glob.Translator(seps: str = _default_seps)

Bases: object

>>> Translator('xyz')
Traceback (most recent call last):
...
AssertionError: Invalid separators
>>> Translator('')
Traceback (most recent call last):
...
AssertionError: Invalid separators
extend(pattern)

Extend regex for pattern-wide concerns.

Apply ‘(?s:)’ to create a non-matching group that matches newlines (valid on Unix).

Append ‘Z’ to imply fullmatch even when match is used.

match_dirs(pattern)

Ensure that zipfile.Path directory names are matched.

zipfile.Path directory names always end in a slash.

replace(match)

Perform the replacements for a match from separate().

restrict_rglob(pattern)

Raise ValueError if ** appears in anything but a full path segment.

>>> Translator().translate('**foo')
Traceback (most recent call last):
...
ValueError: ** must appear alone in a path segment
seps: str
star_not_empty(pattern)

Ensure that * will not match an empty segment.

translate(pattern)

Given a glob pattern, produce a regex that matches it.

translate_core(pattern)

Given a glob pattern, produce a regex that matches it.

>>> t = Translator()
>>> t.translate_core('*.txt').replace('\\\\', '')
'[^/]*\\.txt'
>>> t.translate_core('a?txt')
'a[^/]txt'
>>> t.translate_core('**/*').replace('\\\\', '')
'.*/[^/][^/]*'
zipp.glob.separate(pattern)

Separate out character sets to avoid translating their contents.

>>> [m.group(0) for m in separate('*.txt')]
['*.txt']
>>> [m.group(0) for m in separate('a[?]txt')]
['a', '[?]', 'txt']

Indices and tables