Python decorators are super convenient for making error handling a breeze, but a lot of people don’t know how to use them. Here is a quick tutorial on how they work.
Basically, a decorator is a function that takes another function as input, and provides a wrapper of additional behavior around that function. You apply a decorator to its input function by invoking it with the @ sign above the input function definition, like so:
def generic_decorator(fn):
def wrapper(*args, **kwargs):
return fn() + " Decorated"
return wrapper
@generic_decorator
def f():
return "Hello world"
This can be implemented without decorators, but it will be very syntactically burdensome. The code below implements a generic error handler decorator that can be applied to any robot function and implements a set of behavior if that function encounters an error. In this case, we email a specified email address and log the error to a spreadsheet database.
def robot_error_handler(email_address):
def decorator(fn):
def wrapper(*args, **kwargs):
try:
return fn(*args, **kwargs)
except Exception as e:
print(f"PRANCE Error Handler: {e}")
print(str(e))
email_error(recipient=email_address, error=str(e))
log_error_to_spreadsheet(str(e))
return wrapper
return decorator
Now, just by writing @prance_error_handler(email_address='stefanmgolas@gmail.com')
above a function definition I can encapsulate this function with this generic error handling behavior, for example:
@robot_error_handler(email_address='stefanmgolas@gmail.com')
def robot_function():
raise ValueError('Testing error handler')
I’ve found this very useful, I hope you do too