I wondered recently how practical it would be to do exception handling with
decorators instead of try...except blocks. This would simplify some
functions and methods, and make them easier to read. I found some posts on
the Internet about this, and the upshot is that yes, it can be done at
least in some cases.
Here's an example from some code from my GF4 project. It's a dialog box
that evaluates and returns a floating point number (which can be a Python
expression). This part of the code validates the input:
The original code:
def validate(self):
try:
first= float(eval(self.e1.get()))
self.result = first
return True
except ValueError:
tkMessageBox.showwarning(
"Bad input",
"Illegal value, try again"
)
return False
except SyntaxError:
tkMessageBox.showwarning(
"Syntax Error",
"Fix syntax"
)
return False
except Exception as e:
tkMessageBox.showwarning(
'Error',
"Try again ...%s" % e
)
return False
That's a lot of boiler plate, and not very readable. Here's the code using
decorators:
@val_error(Exception, 'Error ...', "Try again")
@val_error(ValueError, "Bad input","Illegal value, try again")
@val_error(SyntaxError, "Syntax Error", "Fix syntax")
def validate(self):
first= float(eval(self.e1.get()))
self.result = first
return True
This is certainly easier to read and understand. It looks like it's
success-oriented code, but the decorators handle the failure cases. Of
course, there has to be complication somewhere, and in this case it resides
in the *val_error()* decorator. Decorators are somewhat abstract and so
tend to be harder to understand. But they can simplify the using code.
Here's the decorator:
def val_error (except_type, msg1, msg2):
def wrapper(f):
@functools.wraps(f)
def inner(*args, **kwargs):
try:
return f(*args, **kwargs)
except except_type as e:
emsg = f'{e}'.split('(<string')[0]
tkMessageBox.showwarning(f'{msg1}',
f'{emsg}: {msg2}')
return False
return inner
return wrapper
There are various ways to write decorators; for example, they can be done
without using *functools*. I borrowed this particular formulation from
Declutter
python code with error handling decorators
<https://rinaarts.com/declutter-python-code-with-error-handling-decorators/>
.
Whether this approach is worth doing depends on whether the decorator would
be reused some number of times, and on how clever one can be about
constructing the decorator. In the example above, I have a number of
similar variations of the basic dialog, which can all use the same
decorator, so it seems to be very useful. Your mileage may vary.
--
You received this message because you are subscribed to the Google Groups
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/leo-editor/269eb112-6de3-4860-aaeb-fadab60585ean%40googlegroups.com.