18

クラス内のすべてのメソッドによって生成された実行時エラーをキャッチするための例外ハンドラーを作成することは可能ですか?それぞれをtry/exceptで囲むことでそれを行うことができます:

class MyError(Exception):
    def __init__(self, obj, method):
        print 'Debug info:', repr(obj.data), method.__name__
        raise

class MyClass:
    def __init__(self, data):
        self.data = data

    def f1(self):
        try:
            all method code here, maybe failing at run time
        except:
            raise MyError(self, self.f1)

同じことを達成するためのより一般的な方法があるのだろうか-クラスのどこかでエラーが発生した場合。クラスデータにアクセスして、デバッグ情報を出力できるようにしたいと思います。また、失敗したメソッド名(例ではf1)を取得するにはどうすればよいですか?

更新:陰湿な答えをくれたすべての人に感謝します。デコレータのアイデアは進むべき道のように見えます。すべての例外をトラップするリスクについて:ブランチraise内のステートメントは、except情報を失うことなく例外を再発生させる必要がありますね。だから私もMyErrorに入れました...

4

3 に答える 3

25

警告:このようなものが必要な場合は、おそらく必要ありません...しかし、本当に必要な場合は...

何かのようなもの:

import functools

def catch_exception(f):
    @functools.wraps(f)
    def func(*args, **kwargs):
        try:
            return f(*args, **kwargs)
        except Exception as e:
            print 'Caught an exception in', f.__name__
    return func

class Test(object):
    def __init__(self, val):
        self.val = val

    @catch_exception
    def calc():
        return self.val / 0

t = Test(3)
t.calc()

個々の機能を装飾する方法を示しています。次に、クラスデコレータを作成して、このデコレータを各メソッドに適用できます(//などに注意してくださいclassmethod's... )staticmethod'sproperties

于 2012-07-10T19:40:18.260 に答える
18

catch_exception@JonClementの回答のようにデコレータがあると仮定します...

class ErrorCatcher(type):
    def __new__(cls, name, bases, dct):
        for m in dct:
            if hasattr(dct[m], '__call__'):
                dct[m] = catch_exception(dct[m])
        return type.__new__(cls, name, bases, dct)

class Test(object):
    __metaclass__ = ErrorCatcher

    def __init__(self, val):
        self.val = val

    def calc(self):
        return self.val / 0

メタクラスはcatch_exception、を定義している間、メソッドのように見えるすべてのものに適用されますTest


各メソッドのカスタムメッセージに関するコメントに応じて、そのようなメッセージ(またはメッセージを生成するためのコールバック関数)を属性として添付できます。

class Test(object):
    __metaclass__ = ErrorCatcher
    def __init__(self, val):
        self.val = val

    def calc(self):
        return self.val / 0

    calc.msg = "Dividing by 0 is ill-advised"

デコレータは引数の属性を探し、見つかった場合はそれを使用して例外を処理しますcatch_exceptionmsg

このアプローチは拡張できます。文字列の代わりに、msg例外タイプを文字列にマッピングすることもできます。catch_exceptionいずれの場合も、文字列は、たとえば、発生した例外を引数として受け取る任意のコールバック関数に置き換えることができます(もちろん、からのサポートがあります)。

def calc_handler(exc):
    # ...

calc.callback = calc_handler
于 2012-07-10T19:55:19.883 に答える
3

ここではデコレータが良い解決策になります。

これを行う方法の例を次に示します。

import inspect

def catch_exception_decorator(function):
   def decorated_function:
      try:
         function()
      except:
         raise MyError(self.__class__, inspect.stack()[1][3])
   return decorated_function

class MyClass(object):
    def __init__(self):
         ...

    @catch_exception_decorator
    def f1(self):
         ...

関数の上部にある@catch_exception_decoratorは、のショートカットですf1 = catch_exception_decorator(f1)

自分でやる代わりに。classの場合、変数をシャドウイングしない限り、インスタンスからクラスデータにアクセスすることもできます。inspect.stack()[1] [3]は、現在の関数の関数名です。これらを使用して、例外属性を作成できます。

于 2012-07-10T19:53:14.907 に答える