I built robust error handling with targeted except clauses, custom exception types, and structured logging instead of bare prints. Scripts now fail safely, release resources in finally, and record every fault with context for debugging.

Objective & Context

Unhandled exceptions crash automation mid-task and leave systems inconsistent. This lab replaces broad except: blocks with specific handling, adds custom exceptions for domain errors, and routes faults through the logging module, the resilience layer behind the IR automation work.

Environment & Prerequisites

  • Python 3.11 with the logging module.
  • A script that performs I/O or network calls.
  • A log destination (file or stderr).

Step-by-Step Execution

1. Targeted handling with logging

import logging
log = logging.getLogger(__name__)
try:
    data = fetch()
except (TimeoutError, ConnectionError) as e:
    log.error("fetch failed: %s", e)
    raise
finally:
    cleanup()

2. Define a domain exception

python -c "class ConfigError(Exception): pass"

3. Configure logging output

python -c "import logging; logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s')"
2026-06-17 09:14:02 ERROR fetch failed: timed out

Validation & Testing

Force each failure mode (timeout, bad input, missing file) and confirm the right handler runs, cleanup always executes, and the fault is logged with context. Pass criteria: no bare excepts, resources released, and every error logged.

Advanced: Troubleshooting
  • Swallowed errors: never except: pass; at minimum log and re-raise.
  • Lost traceback: use log.exception() inside an except to capture the stack.
  • Resource leaks: prefer context managers or finally for cleanup.

Key Results

  • Replaced broad excepts with specific handling across the codebase.
  • Logged 100% of faults with timestamp, level, and context.
  • Guaranteed resource cleanup via finally and context managers.
  • Introduced custom exceptions for clear domain error signaling.