Exceptions for the whole class

别等时光非礼了梦想. 提交于 2019-12-06 03:09:35

问题


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?


回答1:


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 functools

def handle_with(handler, *exceptions):
    try:
        handler, cleanup = handler
    except TypeError:
        cleanup = lambda f, e: None
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except exceptions or Exception as e:
                return handler(func, e)
            finally:
                cleanup(func, e)
        return wrapper
    return 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 = handler
    except TypeError:
        cleanup = lambda e: None
    try:
        yield
    except exceptions or Exception as e:
        handler(e)
    finally:
        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.




回答2:


I can think of two options:

  1. Write a decorator that can wrap each method in the try block.
  2. Write a "dispatcher" method that calls the appropriate method inside a try block, then call that method instead of the individual ones. That is, instead of calling obj.someMethod(), obj.otherMethod, you call obj.dispatch('someMethod') or obj.dispatch('otherMethod'), where dispatch is a wrapper that contains the try block.

Your approach seems like a bit of a strange design, though. It might make more sense to have the dialog-box stuff in some other part of the code, some higher-level event loop that catches errors and displays messages about them.



来源:https://stackoverflow.com/questions/19232373/exceptions-for-the-whole-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!