Errors in Python
In Python, error handling is typically done using exceptions rather than explicit error return values. However, we can simulate a similar approach to demonstrate the concept. Here’s how we might implement a similar error handling pattern in Python:
from typing import Tuple, Union
# By convention, we'll use a tuple to return both a value and an error
def f(arg: int) -> Tuple[int, Union[str, None]]:
if arg == 42:
# We return a tuple with the error value and an error message
return -1, "can't work with 42"
# A None value in the error position indicates that there was no error
return arg + 3, None
# Sentinel errors are typically implemented as custom Exception classes in Python
class OutOfTeaError(Exception):
pass
class PowerError(Exception):
pass
def make_tea(arg: int) -> None:
if arg == 2:
raise OutOfTeaError("no more tea available")
elif arg == 4:
# We can wrap errors by catching and re-raising with additional context
try:
raise PowerError("can't boil water")
except PowerError as e:
raise Exception(f"making tea: {str(e)}") from e
return None
def main():
for i in [7, 42]:
# It's common to use a try-except block for error handling in Python
try:
r, e = f(i)
if e is not None:
print(f"f failed: {e}")
else:
print(f"f worked: {r}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
for i in range(5):
try:
make_tea(i)
print("Tea is ready!")
except OutOfTeaError:
print("We should buy new tea!")
except PowerError:
print("Now it is dark.")
except Exception as e:
print(f"unknown error: {str(e)}")
if __name__ == "__main__":
main()
In this Python version:
We use tuples to simulate Go’s multiple return values for errors.
Instead of a built-in
error
interface, we useNone
to indicate no error and a string (or custom Exception) for error messages.Sentinel errors are implemented as custom Exception classes.
We use exceptions and try-except blocks for error handling, which is more idiomatic in Python.
Error wrapping is simulated by catching and re-raising exceptions with additional context.
The
errors.Is()
functionality is replaced with exception type checking in except clauses.
When you run this program, you should see output similar to:
f worked: 10
f failed: can't work with 42
Tea is ready!
Tea is ready!
We should buy new tea!
Tea is ready!
Now it is dark.
This example demonstrates how to implement a similar error handling pattern in Python, although it’s worth noting that this is not typically how errors are handled in idiomatic Python code. Python generally favors a “ask for forgiveness, not permission” approach using try-except blocks for error handling.