1

問題のある関数 (変更可能なページの HTML 解析) で例外をログに記録したいので、時間、例外の種類、コード内の例外の行、関数呼び出しの引数など、例外をファイルに記録するある種のデコレータがここで最善の解決策だと思います。次のようなもの:

@exception_catch(log_path='example.log')
def example(x,y):
    raise Exception('123')

そのような種類のタスクを解決するためのベストプラクティスは何ですか、またはこれに適したpythonライブラリである可能性がありますか?

4

2 に答える 2

2

おそらく unutbu が示唆するようにしたいと思うでしょう。なぜなら、それはより柔軟で、最終的には同じくらい単純だからです. しかし、 の追加の詳細に圧倒された場合は、次loggingのようにして、まさにあなたが要求したことを行う方法を示します。

def exception_catch(log_path):
    def deco(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except Exception as e:
                with open(log_path, 'a') as log:
                    log.write('{} {} {} {} {}\n'.format(datetime.datetime.now(), 
                                                        type(e), e, args, kwargs))
                # This will return None on error, of course
        return wrapper
    return deco

formatもちろん、上記のスコープのローカル変数を含め、必要なものを に入れることができます。あなたが求めたものの唯一のトリッキーなビットは、「コード内の例外行」です。その詳細は 2.x と 3.x では少し異なります (traceback知っておくべきことのほとんどについては、モジュールを参照してください)。

except Exception as e:
    filename, line, func, text = traceback.extract_stack(limit=1)[0]
    with open(log_path, 'a') as log:
        log.write('time: {} type: {} line: {} args: {}\n'.format(
            datetime.datetime.now(), 
            type(e),
            line,
            args))    
于 2013-04-17T20:11:48.103 に答える
2

ファイルへのパスを渡す代わりに、代わりにロガーを渡します。そうすれば、デコレーターのユーザーは、ファイルまたはコンソールなどにログを記録するかどうかを決定できます。ロガーは、ログ メッセージの形式も決定します。

exceptionキャッチする例外の種類をパラメーターで定義することもできます。(以下では、 のor タプルをexception取ることができます。ExceptionExceptions


import logging

def catch_exception(exception=Exception, logger=logging.getLogger(__name__)):
    def deco(func):
        def wrapper(*args, **kwargs):
            try:
                result = func(*args, **kwargs)
            except exception as err:
                logger.exception(err)
            else:
                return result
        return wrapper
    return deco

@catch_exception()
def example(x,y):
    raise Exception('123')

logging.basicConfig(filename='/tmp/error.log', level=logging.DEBUG,
                    datefmt='%Y-%m-%d %H:%M:%S',
                    format='%(asctime)s %(module)s %(levelname)s: %(message)s')

example(1,2)
于 2013-04-17T19:45:19.303 に答える