3

これはこれまでで最もばかげた質問かもしれませんが、例外が発生した場合にローカル変数の内部状態をキャッチできるように、関数 (できればデコレータ) の周りにラッパーを記述する方法があるかどうかを知りたいです。その関数で発生します。作成時にローカルをキャッチし、それらをピクルし、例外が発生しなかった場合はそれらを破棄し、例外が見つかった場合はそれらをファイルに書き込みます。

これはあまりにも空想的ですか、それとも誰かがこのようなことでだまされましたか?

4

2 に答える 2

5

f_localstraceback のフレームで変数をキャプチャできます。

import sys
import functools

def capturelocals(func):
    @functools.wraps(func)
    def wrapperfunc(*args, **kw):
        try:
            return func(*args, **kw)
        except Exception:
            _, _, tb = sys.exc_info()
            try:
                while tb.tb_next is not None:
                    tb = tb.tb_next  # find innermost frame
                locals = tb.tb_frame.f_locals
                print locals
            finally:
                del tb  # prevent leaking tracebacks
            raise
    return wrapperfunc

それが機能することを実証するには:

>>> @capturelocals
... def foobar():
...     foo = 'bar'
...     spam = 'eggs'
...     raise ValueError('Bam!')
... 
>>> foobar()
{'foo': 'bar', 'spam': 'eggs'}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in wrapperfunc
  File "<stdin>", line 5, in foobar
ValueError: Bam!
于 2013-02-06T00:48:24.317 に答える
1

別のオプションは、壊滅的な事態が発生した場合に保存したい変数だけを引数として関数に渡すことです。

これを行うのに役立つデコレータ:

import os
try:
    import cPickle as pickle
except ImportError:
    import pickle

def save_args_if_exception(pickle_folder):
    def real_decorator(function):
        def wrapper(*args, **kwargs):
            try:
                function(*args, **kwargs)
            except:
                print 'FAILING SAFE: Saving arguments to folder:'
                print pickle_folder
                for arg_position, arg in enumerate(args, start=1):
                    arg_fname = os.path.join(pickle_folder, str(arg_position) +
                                             '.pickle')
                    print 'Saving positional argument-{}'.format(arg_position)
                    with open(arg_fname, mode='wb') as f:
                        pickle.dump(arg, f)
                print 'Saving keyword arguments (kwargs)'
                with open(os.path.join(pickle_folder, 'kwargs.pickle'),
                          mode='wb') as f:
                    pickle.dump(kwargs, f)
                raise  # re-raise original exception
        return wrapper
    return real_decorator

@save_args_if_exception(os.getcwd())
def important_function(first_arg, second_arg=2, **kwargs):
    print 'About to raise an exception!'
    raise Exception

important_function(3)

この例でsecond_argは、 はファイルに保存されないことに注意してください。おそらく、Python がデフォルト引数を処理する方法が原因です。状況に応じて、これは有用な動作である場合とそうでない場合があります。

参考文献:

于 2013-02-06T01:03:44.140 に答える