Home/Python/Errors and exceptions

Errors and exceptions

Raise clear errors and catch failures at useful boundaries

Raising and catching errors

An exception reports that an operation could not produce its normal result. A traceback identifies the exception and the calls leading to it. Read the final line for the immediate failure, then inspect the relevant frames.

Use a narrow try block and catch specific exception types. Other errors propagate to the caller. Parsing and domain validation can fail separately:

Python
def read_percentage(text):
    number = int(text)
    if not 0 <= number <= 100:
        raise ValueError("percentage must be between 0 and 100")
    return number

try:
    read_percentage("120")
except ValueError as error:
    print(error)  # percentage must be between 0 and 100

Here conversion succeeds, but the range is invalid. An input such as "many" fails during conversion. Both are ValueError because the supplied value is unacceptable.

Cleanup and propagation

  • else runs when the try body completes normally.
  • finally runs during ordinary exits, including exceptions and returns. Use it for cleanup.
  • Bare raise re-raises the active exception.
  • raise ... from error preserves the cause when translating between error categories.

A custom exception gives callers a stable category across lower-level failures:

Python
class InvalidConfiguration(Exception):
    pass

def read_port(settings):
    try:
        return int(settings["port"])
    except (KeyError, ValueError) as error:
        raise InvalidConfiguration("port is missing or invalid") from error

try:
    read_port({"port": "many"})
except InvalidConfiguration as error:
    print(type(error.__cause__).__name__)  # ValueError

__cause__ preserves the conversion error. A wrong runtime type such as a list still raises TypeError; the handler deliberately translates only KeyError and ValueError. This example checks representation, not the valid port range.

Gotchas

  • Catch where recovery is possible: reject a row, ask for another value, or stop. A broad catch that returns zero can turn a defect into plausible data.
  • Bare except: also catches termination requests such as KeyboardInterrupt. Routine recovery should catch specific Exception subclasses.
  • return in finally can replace a result or suppress a pending exception. Cleanup failures can also replace the visible error.
  • If a batch continues after rejection, retain the failure details and define whether earlier side effects remain committed.

Use custom categories when callers need them. Test error types and state after failure; require exact messages only when they are part of the interface.

Put it into practice

Implement the exercise in a full-screen workspace, then run its tests.

Open practice
Next lessonModules, files, and JSON