A back-port of Python 3.15's sentinel builtin for older Python versions.
On Python 3.15+, you can write:
MISSING = sentinel("MISSING") DEFAULT = sentinel("DEFAULT", repr="<DEFAULT>")
This package provides the same behaviour on every supported Python version (3.10+) via a small, focused API.
Sentinel objects are an idiomatic way to distinguish “no value provided”
from “value is None” — useful for default arguments, optional caches,
and any function parameter that needs a tri-state (unset / None /
real value).
from sentinel import sentinel MISSING = sentinel("MISSING") def fetch(key: str, default=None): """``default`` may legitimately be ``None``; ``MISSING`` means ``fetch`` should compute the fallback itself.""" ...
pip install pythonbackport-sentinel
from sentinel import sentinel MISSING = sentinel("MISSING") MISSING # -> 'MISSING'
from sentinel import sentinel MISSING = sentinel("MISSING", repr="<MISSING>") MISSING # -> '<MISSING>'
from sentinel import sentinel A = sentinel("A") B = sentinel("A") # a *different* object with the same name assert A # truthy assert A is A # identity equality assert A is not B # even with the same name, A != B
from sentinel import sentinel MISSING = sentinel("MISSING") def next_value(default: int | MISSING = MISSING): ...
import pickle from sentinel import sentinel PICKLABLE = sentinel("PICKLABLE") assert pickle.loads(pickle.dumps(PICKLABLE)) is PICKLABLE
import pickle from sentinel import sentinel class Cls: PICKLABLE = sentinel("Cls.PICKLABLE") assert pickle.loads(pickle.dumps(Cls.PICKLABLE)) is Cls.PICKLABLE
Return a new unique sentinel object.
name(positional-only, required) —str; the sentinel's name, used as the default representation.repr(keyword-only, optional) —str; an alternative representation. Defaults toname.
| Attribute | Read | Write | Description |
|---|---|---|---|
__name__ |
✅ | ❌ | The sentinel's name. |
__module__ |
✅ | ✅ | The module that created the sentinel (writable, str). |
- Always truthy (
bool(s) is True). - Equal only to itself; use the
isoperator. - Cannot be subclassed.
copy.copy(s)andcopy.deepcopy(s)both returns.s | TandT | sbuild a usable Union type for annotations.- Pickling preserves identity when the sentinel is defined at module or class scope with a name that matches the variable (or, for class scope, the qualified name).
When you are running on Python 3.15+, sentinel is a true builtin.
The package's own API still works identically, so you can use either:
# Native (Python 3.15+ only): MISSING = sentinel("MISSING") # Cross-version equivalent via this package: from sentinel import sentinel MISSING = sentinel("MISSING")
- Python 3.10 through 3.15 (uses PEP 604 unions; falls back to
typing.Unionon older interpreters). - No third-party dependencies — uses only the standard library
(
pickle,sys,types).
python -m unittest test_sentinel.py -v
This project will reach its end-of-life around October 1, 2031 — the
official EOL date of Python 3.15 — and the exact timeline could be
slightly delayed. We plan to ship the final stable release in November
2031. After this release, all support will cease and the repository
will be officially archived, as this library is developed solely to
bring sentinel() compatibility to Python 3.15 and older versions.
MIT