Skip to main content

AI-powered try/catch: explains unexpected errors and generates ready-to-paste fixes using OpenAI.

Project description

SmartCatch ๐Ÿšจ๐Ÿค–

AI-powered exception handling for Python.
SmartCatch wraps your code in a smart try/catch that, when an unexpected error slips through, automatically:

  1. Explains exactly which line caused the error and why.
  2. Generates a ready-to-paste fix snippet you can drop straight into your code.
  3. Advises on how to prevent that class of error in the future.

It uses the OpenAI API (zero extra dependencies โ€” pure stdlib) and works as a decorator, a context manager, or a global exception hook.


Installation

pip install smartcatch

Set your OpenAI key once (or pass it via SmartCatchConfig):

export OPENAI_API_KEY="sk-..."

Quick start

1 โ€” Decorator

from smartcatch import smartcatch

@smartcatch
def load_config(path):
    with open(path) as f:
        return json.load(f)   # FileNotFoundError? JSONDecodeError? SmartCatch handles it.

load_config("settings.json")

2 โ€” Context manager

from smartcatch import SmartCatchContext

with SmartCatchContext():
    result = int(user_input) / divisor   # ZeroDivisionError? ValueError? Caught + explained.

3 โ€” Global hook (catch everything)

Put this at the very top of your main.py or entry point:

import smartcatch
smartcatch.install_global_handler()

# โ€ฆ rest of your app โ€ฆ

Any unhandled exception anywhere in the process will be analysed automatically.


What the output looks like

โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
  ๐Ÿšจ  SMARTCATCH โ€” Unexpected Error Detected
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

  Exception : ZeroDivisionError: division by zero

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
  ๐Ÿ“Œ  What happened
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

  Division by zero occurred on line 12 of app.py.

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
  ๐Ÿ”  Root cause
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

  The variable `divisor` is 0 at line 12 because no guard is in place
  before the division `value / divisor`.

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
  ๐Ÿ› ๏ธ   Ready-to-integrate fix
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

    # Guard against zero divisor before performing division
    if divisor == 0:
        raise ValueError("divisor must not be zero")
    result = value / divisor

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
  ๐Ÿ’ก  Prevention advice
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

  Always validate numeric inputs before performing arithmetic. Consider
  using a helper function that raises a descriptive error on bad values.

โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

Configuration

All behaviour is controlled via SmartCatchConfig:

from smartcatch import SmartCatchConfig, smartcatch, SmartCatchContext, install_global_handler

cfg = SmartCatchConfig(
    api_key="sk-...",          # or set OPENAI_API_KEY env var
    model="gpt-4o",            # any OpenAI chat model
    max_source_lines=30,       # lines of source context sent to the model
    show_fix=True,             # print the fix snippet
    show_explanation=True,     # print the root-cause explanation
    reraise=True,              # re-raise after analysis (default True)
    output_file="errors.log",  # write report to a file instead of stderr
    silent=False,              # suppress all output (useful with output_file)
)

@smartcatch(config=cfg)
def my_function():
    ...

with SmartCatchContext(config=cfg):
    ...

install_global_handler(config=cfg)

Catch only specific exception types

@smartcatch(catch=(ValueError, KeyError))
def parse(data):
    ...

with SmartCatchContext(catch=(IOError,)):
    ...

How it works

  1. The handler intercepts the exception before Python unwinds the stack.
  2. It extracts the full traceback + annotated source lines around each frame using linecache.
  3. It sends that context to gpt-4o via a single structured prompt that demands a JSON response.
  4. The JSON is parsed into an AnalysisResult and printed (or written to a file).
  5. The original exception is re-raised (unless reraise=False).

No third-party libraries are required โ€” only urllib, json, traceback, and linecache from the Python standard library.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

smartcatch-0.1.0.tar.gz (3.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

smartcatch-0.1.0-py3-none-any.whl (3.2 kB view details)

Uploaded Python 3

File details

Details for the file smartcatch-0.1.0.tar.gz.

File metadata

  • Download URL: smartcatch-0.1.0.tar.gz
  • Upload date:
  • Size: 3.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for smartcatch-0.1.0.tar.gz
Algorithm Hash digest
SHA256 f6bc2c4c78f6427c594160bd037096d3fedabd2cfd8ae70616e731f476026998
MD5 3d73a4493ab4e8d61415a73e6dc3edde
BLAKE2b-256 fb80c735c94d57feb0f44ed18b59a1a85ba8470026376ae0c40169020154383c

See more details on using hashes here.

File details

Details for the file smartcatch-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: smartcatch-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 3.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for smartcatch-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 54c7a4a24642feffa48f21a7484e2d70a8039f53ca6115947c426fee5c65ed5b
MD5 8af7c94a7cd3e16f2b9c11945d641aa4
BLAKE2b-256 4a29071996410b8ed610f130ee747fc075f2f860f6287a14c094ec116f7fc770

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page