Failover for long python scripts

This may be the dumbest question, but I would like to know if there is a way to write a wrapper around a function (preferably a decorator) so that you can catch the internal state of local variables if an exception was thrown in this function. He would catch the locals as they were created, sort them, and then get rid of them if there were no exceptions, or write them to a file if any exceptions were found.

Is it too bizarre, or has someone tricked themselves into something like this?

+3
source share
2 answers

You can capture a variable f_localsin a frame in a trace :

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!
+5

- , - .

, :

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 . .

:

+1

Source: https://habr.com/ru/post/1728272/


All Articles