I'm writing a program in Python, and nearly every method im my class is written like this:
def someMethod(self):try:#...except someException:#in case of exception, do something here#e.g display a dialog box to inform the user #that he has done something wrong
As the class grows, it is a little bit annoying to write the same try-except block over and over. Is it possible to create some sort of 'global' exception for the whole class? What's the recommended way in Python to deal with this?
Write one or more exception handler functions that, given a function and the exception raised in it, does what you want to do (e.g. displays an alert). If you need more than one, write them.
def message(func, e):print "Exception", type(e).__name__, "in", func.__name__print str(e)
Now write a decorator that applies a given handler to a called function:
import functoolsdef handle_with(handler, *exceptions):try:handler, cleanup = handlerexcept TypeError:cleanup = lambda f, e: Nonedef decorator(func):@functools.wraps(func)def wrapper(*args, **kwargs):try:return func(*args, **kwargs)except exceptions or Exception as e:return handler(func, e)else:e = Nonefinally:cleanup(func, e)return wrapperreturn decorator
This only captures the exceptions you specify. If you don't specify any, Exception
is caught. Additionally, the first argument can be a tuple (or other sequence) of two handler functions; the second handler, if given, is called in a finally
clause. The value returned from the primary handler is returned as the value of the function call.
Now, given the above, you can write:
@handle_with(message, TypeError, ValueError)
def add(x, y):return x + y
You could also do this with a context manager:
from contextlib import contextmanager @contextmanager
def handler(handler, *exceptions):try:handler, cleanup = handlerexcept TypeError:cleanup = lambda e: Nonetry:yieldexcept exceptions or Exception as e:handler(e)else:e = Nonefinally:cleanup(e)
Now you can write:
def message(e):print "Exception", type(e).__name__print str(e)def add(x, y):with handler(message, TypeError, ValueError):return x + y
Note that the context manager doesn't know what function it's in (you can find this out, sorta, using inspect
, though this is "magic" so I didn't do it) so it gives you a little less useful information. Also, the context manager doesn't give you the opportunity to return anything in your handler.