bytes.rpartition()
partition from the other end. The absent-separator rule is mirrored too: partition fills the HEAD, rpartition fills the TAIL. Getting that backwards is the whole failure mode.
Demo
The split happens at the LAST occurrence, so a=b=c gives a=b as the head and c as the tail — the opposite grouping from partition. The extension case is the classic use: file.tar.gz splits into file.tar and gz. Study the absent case closely, because it is mirrored from partition: with no separator, rpartition puts the whole input in the TAIL, giving two empty parts first.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| sep | bytes | yes | Separator to split on, at its last occurrence. An empty separator raises ValueError. |
Return value
tuple — Always (head, separator, tail), split at the LAST occurrence. When the separator is absent, the tail holds everything and the other two are empty — the mirror of partition.
Common patterns
stem, _, ext = name.rpartition(b'.')
directory, _, leaf = path.rpartition(b'/')
host, _, port = addr.rpartition(b':')
Examples
Pitfalls
b'noext'.rpartition(b'.')[0]
h, s, t = name.rpartition(b'.') stem = h if s else t
b'a=b=c'.rpartition(b'=')
b'a=b=c'.partition(b'=')
b'abc'.rpartition(b'')
parts = d.rpartition(sep) if sep else (b'', b'', d)
When to use
- File extensions, path leaves and host:port — anything keyed on the LAST separator
- Key-value parsing where the value may itself contain the separator
- Anywhere rfind plus slicing would need a -1 check
- The FIRST separator → partition
- Every field → split or rsplit
- Real paths → os.path or pathlib handle edge cases
Notes
FAQ
So that the tail always means "everything after the last separator". With no separator there is nothing before it, so the whole input is "after". It also makes name.rpartition(b".")[2] a safe way to take the extension-or-whole-name in one expression.
b'abc'.rpartition(b'=') # (b'', b'', b'abc')