A lightweight Python exception handling utility library.
Something need change or refactor? Contact email errortools.docs@proton.me
pip install errortoolsuv add errortools- Suppress:
ignore(),super_fast_ignore(),@suppress()— silence exceptions gracefully - Retry & Timeout:
@retry(),@timeout()— auto retry with delay, async timeout - Raise & Convert:
raises(),reraise(),@convert()— batch raise, type conversion - Catch & Collect:
super_fast_catch(),ExceptionCollector— inspect or batch exceptions - Caching:
@error_cache— LRU exception cache, likefunctools.lru_cache - Custom Exceptions:
PureBaseException,ContextException,BaseErrorCodes - Logging: structured logger with sinks, context binding, and exception capture
fromerrortoolsimportignore, retry, reraise, error_cache, suppress, convertfromerrortools.futureimportsuper_fast_ignore, super_fast_catch, ExceptionCollector# ── Suppress ─────────────────────────────────────────────────withignore(KeyError) aserr: # full metadata_= {}["missing"]
# err.be_ignore=True, err.name='KeyError', err.traceback=...withsuper_fast_ignore(ValueError): # zero-overheadint("bad")
@suppress(ZeroDivisionError, default=0) # decorator formdefdivide(a, b): returna/b# ── Retry ────────────────────────────────────────────────────@retry(times=3, on=ConnectionError, delay=1.0)defconnect(host: str): ...
# ── Convert ──────────────────────────────────────────────────@convert(KeyError, ValueError) # decoratordeflookup(d, key): returnd[key]
withreraise(KeyError, ValueError): # context managerraiseKeyError("x") # → ValueError# ── Catch & Collect ──────────────────────────────────────────withsuper_fast_catch(ValueError) asctx:
raiseValueError("oops")
# ctx.exception → ValueError('oops')collector=ExceptionCollector()
collector.catch(int, "bad1")
collector.catch(int, "bad2")
collector.raise_all() # → ExceptionGroup# ── Cache ────────────────────────────────────────────────────@error_cache(maxsize=64)defload(uid: int):
ifuid<0: raiseValueError(f"invalid: {uid}")
return {"id": uid}fromerrortoolsimportPureBaseException, ContextException, BaseErrorCodesclassAppError(PureBaseException):
code=9000default_detail="Application error."err=ContextException("failed").with_context(service="db")
raiseBaseErrorCodes.not_found("user #42") # NotFoundError [3001]fromerrortools.loggingimportloggerlogger.info("Server started on port {}", 8080)
logger.add("app.log", rotation=10_485_760, retention=5)
withlogger.catch():
int("not a number") # logged + suppressedFull docs: docs | License: LICENSE
Main email: errortools@proton.me Support email: errortools-support@proton.me Security email: errortools-security@proton.me Agents contact email: errortools.agent-preview@proton.me