Errors

Exception Chaining

raise from preserves the original cause when translating exceptions.

Catch the low-level exception where it happens, then raise a domain-specific exception from it.

Source

class ConfigError(Exception):
    pass


def read_port(text):
    try:
        return int(text)
    except ValueError as error:
        raise ConfigError("port must be a number") from error

print(ConfigError.__name__)

Output

ConfigError
ValueError__cause____context__RuntimeError
`raise X from Y` sets `__cause__` (explicit); raising during except sets `__context__` (implicit).

The caller handles the domain error. The original ValueError remains available as __cause__.

Source

try:
    read_port("abc")
except ConfigError as error:
    print(error)
    print(type(error.__cause__).__name__)

Output

port must be a number
ValueError

Notes

See also

Run the complete example

Example code

Expected output

ConfigError
port must be a number
ValueError

Execution time appears here after you run the example.