Rust-like error handling in Python with NamedTuple
I’m a fan of Rust’s error handling model. If a function encounters an error, it returns an error value (called Result in Rust) and leaves it up to the caller to decide what to do with that value. In Python, we have exceptions for this case, but sometimes I miss Rust’s model. For example, when writing tests, I often find myself wanting to return errors from my mock functions instead of raising exceptions.
Trying to replicate this behavior with Python’s built-in exception handling leaves something to be desired: it’s not quite as convenient or powerful as Rust’s approach. However, we can come close by leveraging Python’s NamedTuple, which provides us with a way to create our own custom named data structures.
The code
Explanation
Where constructs like
Ok = lambda val: TokenResult(val, None)Err = lambda **err: TokenResult(“”, err)
defines functional datatypes for the returned values. Both of those derived from `TokenResult` and convenient to use in the type annotation
def try_exchange_token(jwt: str) -> TokenResult:
While statement like
new_token, error = try_exchange_token(...) if error:
return error
automatically leverages tuple unpack and error handling
Key-takeaway
NamedTuple was not meant to be a comprehensive Rust-like error handling system, but rather a pragmatic alternative in cases where a Rust-like structure would make sense. In this respect, it is really up to the programmer using NamedTuple to decide the level of experience they want with error handling in Python.