Skip to main content

Crash Catcher

Crash Catcher is a decorator to catch exceptions in a python function and log them to a file. Supports optional callbacks to perform cleanup operations before the crash log is written.

Synopsis

"""Demo crash_catcher with a simple example."""

from .crash_catcher import (
    crash_catcher,
    register_crash_callback,
    set_crash_data,
    unregister_crash_callback,
)


@crash_catcher(
    filename="crash_catcher.log",
    message="The app has crashed",
    title="Crash catcher demo",
    postamble="Please file a bug report with contents of '{filename}'",
    overwrite=True,
    extra={"extra": "data"},
)
def demo_crash_catcher():
    """Demo crash_catcher decorator"""
    set_crash_data("globals", globals())
    set_crash_data("locals", locals())
    print("Hello world")

    # some critical section that requires cleanup
    callback_id = register_crash_callback(lambda: print("Cleaning up..."))

    # any uncaught exception causes the crash_catcher decorator to catch the crash
    raise ValueError("Oh no, the app has crashed!")

    # exit critical section and deregister callback
    unregister_crash_callback(callback_id)


if __name__ == "__main__":
    demo_crash_catcher()

Rationale

This decorator is intended to be used with python command line apps where you want to catch exceptions and display a nice message to the user instead of a stack trace. The stack trace and other crash data is logged to a file which you can then direct the user to send to you.

Instead of a traceback, the user sees a message like this:

Hello world
The app has crashed
Oh no, the app has crashed!
Cleaning up...
Crash log written to 'crash_catcher.log'
Please file a bug report with contents of 'crash_catcher.log'

Installation

python3 -m pip install crash-catcher

Usage

Import crash_catcher and apply the decorator to your main function. The decorator takes the following arguments:

  • filename: The name of the file to write the crash log to.
  • message: The message to display to the user when the app crashes.
  • title: The title of the message box displayed to the user.
  • postamble: Optional text to display to the user after the message. Defaults to None.
  • overwrite: Whether to overwrite the crash log file if it already exists. If False, the crash filename will be incremented until a non-existent filename is found. Defaults to False.
  • **extra: Optional **kwargs of extra data to include in the crash log.

For example:

from crash_catcher import crash_catcher

@crash_catcher(
    filename="crash_catcher.log",
    message="The app has crashed",
    title="Crash catcher demo",
    postamble="Please file a bug report with contents of '{filename}'",
    overwrite=True,
    extra="data",
)
def main():
    # do stuff
    raise ValueError("Oh no, the app has crashed!")

if __name__ == "__main__":
    main()

In the decorated function, you may use the following utility functions to change the behavior of the crash catcher:

  • set_crash_data(key, value): Set a key/value pair in the crash log. The key and value will be printed to the crash log.
  • register_crash_callback(func: Callable[[], None], message: str | None = None) -> int: Register a callback to be called when the app crashes. The callback will be called before the crash log is written and can be used to perform any cleanup operations, for example, deleting files or closing database connections. The optional message will be printed when calling the callback. Returns a callback id which can be used to unregister the callback with unregister_crash_callback.
  • unregister_crash_callback(callback_id: int): Unregister a callback. The callback will no longer be called when the app crashes. Use the callback_id returned by register_crash_callback to unregister the callback.

Crash Log

The crash log file contains the following information:

  • Title as defined by the title argument to the decorator.
  • Date and time of the crash.
  • System information including platform, python version, python path, and command line arguments.
  • Crash data including any data set with set_crash_data and the traceback of the crash.
Crash catcher demo
Created: 2023-11-13 17:11:09.302745

SYSTEM INFO:
Platform: macOS-13.5.1-x86_64-i386-64bit
Python: /Library/Frameworks/Python.framework/Versions/3.11/bin/python3.11
Python version: 3.11.6 (v3.11.6:8b6ee5ba3b, Oct  2 2023, 11:18:21) [Clang 13.0.0 (clang-1300.0.29.30)]
Python path: [...]
sys.argv: ['myapp.py']

CRASH DATA:
demo_crash_catcher called by <module> at 2023-11-13T17:11:09.301593 crashed after 3.982799535151571e-05 seconds
args=()
kwargs={}
globals: {...}
locals: {...}
extra: {'extra': 'data'}
Error: Oh no, the app has crashed!
Traceback (most recent call last):
  File "myapp.py", line 115, in wrapped
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "myapp.py", line 29, in demo_crash_catcher
    raise ValueError("Oh no, the app has crashed!")
ValueError: Oh no, the app has crashed!

Documentation

See the documentation for more details.

License

Crash Catcher is published under the MIT license, © 2023, Rhet Turnbull.

Dependencies

No dependencies outside the standard library.

Contributing

Contributions of all kinds are welcome!

See Also

  • error-catcher which provides a similar decorator to improve tracebacks (but not logging to file).
  • crashreport which provides a way to inject an exception handler that logs to file.

Metadata

Release files for crash-catcher 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for crash-catcher 0.2.2
File Size Uploaded Provenance
crash_catcher-0.2.2.tar.gz 9.0 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for crash-catcher 0.2.2
File Interpreter ABI Platform
crash_catcher-0.2.2-py2.py3-none-any.whl Python 3, Python 2 none any Details

Total release size: 16.6 kB

Release files / crash_catcher-0.2.2.tar.gz

Download URL crash_catcher-0.2.2.tar.gz
Size 9.0 kB
Tags Source
SHA-256 checksum
How to use checksums
140115c89c1a4bf6ace4a78dfe34b84f2c26b7352a926a24fc24b262c7e782e5
BLAKE2b-256 checksum
How to use checksums
a9d5852c89b246681a536b1647451863a094fa1d73a283d2c74c8a1a6ddec1d3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-requests/2.31.0

Release files / crash_catcher-0.2.2-py2.py3-none-any.whl

Download URL crash_catcher-0.2.2-py2.py3-none-any.whl
Size 7.6 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
5f1b78f561d76dc5407ce5245a61b374a4cecbf8e5e751d1aed6b4606be8d543
BLAKE2b-256 checksum
How to use checksums
1abd869fd3ec4a03f4808d057e0a62f78c6ed8dfa658b2988ac52e189710d703
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-requests/2.31.0

Security for crash-catcher 0.2.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page