首页 > 解决方案 > 如何在不嵌入所有容器内容的情况下转储和保存函数参数?

问题描述

我试图在运行时将所有函数参数保存到容器中。容器对于脚本中运行的所有函数都是通用的。如何确保每次保存函数参数时都不会保存所有容器的内容?

下面的装饰器保存函数参数:

import inspect
from datetime import datetime
import time

def func_logger(method):
    def wrapper(*args, **kw):
        method_args = inspect.signature(method).bind(*args, **kw).arguments

        runtime     = str( datetime.now() )
        name        = method.__name__
        module      = method.__module__
        signature   = runtime + ': ' + '.'.join([module, name])

        ts     = time.time()
        result = method(*args, **kw)
        te     = time.time()

        kw['log'][signature] = {}
        kw['log'][signature]['time'] = round(te - ts, 2)
        kw['log'][signature]['args'] = method_args

        return result
    return wrapper

还有一个示例函数:

@func_logger
def test(a, b=4, c='blah-blah', *args, **kwargs):
    return 4**4**8

当我运行以下代码段时:

log = {}
output = test(1,4,2,4,1,par=1, log=log)
output = test(1,4,2,4,1,par=1, log=log)

log

我收到这个输出:

{'2019-05-17 13:48:25.214094: __main__.test': {'time': 0.0,
  'args': OrderedDict([('a', 1),
               ('b', 4),
               ('c', 2),
               ('args', (4, 1)),
               ('kwargs', {'par': 1, 'log': {...}})])},
 '2019-05-17 13:48:25.215092: __main__.test': {'time': 0.0,
  'args': OrderedDict([('a', 1),
               ('b', 4),
               ('c', 2),
               ('args', (4, 1)),
               ('kwargs', {'par': 1, 'log': {...}})])}}

我已经尝试过一种解决方法 - 从字典中删除“日志”条目的功能。但是,此日志中的每个下一项都存储日志的当前内容。所以当我尝试这个时:

list( log.items() )[-1][-1]['args']

输出是这样的:

OrderedDict([('a', 1),
             ('b', 4),
             ('c', 2),
             ('args', (4, 1)),
             ('kwargs',
              {'par': 1,
               'log': {'2019-05-17 13:45:45.748722: __main__.test': {'time': 0.0,
                 'args': OrderedDict([('a', 1),
                              ('b', 4),
                              ('c', 2),
                              ('args', (4, 1)),
                              ('kwargs', {'par': 1, 'log': {...}})])},
                '2019-05-17 13:45:45.749221: __main__.test': {'time': 0.0,
                 'args': OrderedDict([('a', 1),
                              ('b', 4),
                              ('c', 2),
                              ('args', (4, 1)),
                              ('kwargs', {'par': 1, 'log': {...}})])},
                '2019-05-17 13:45:45.750218: __main__.test': {'time': 0.0,
                 'args': OrderedDict(...)}}})])

所以本质上,这样的解决方法是行不通的,因为随着时间的推移,内存会很快被堵塞。

每次我保存函数参数时,装饰器是否有任何方法不会保存日志条目?我宁愿避免每次我想从新函数转储参数时创建一个新的“log = {}”容器。

标签: python

解决方案


您可以简单地存储 log 参数(如果存在)并将其从以下位置删除**kw

def func_logger(method):
    def wrapper(*args, **kw):
        try:
            log = kw['log']
            del kw['log']
        except KeyError:
            log = None

        method_args = inspect.signature(method).bind(*args, **kw).arguments

        runtime     = str( datetime.now() )
        name        = method.__name__
        module      = method.__module__
        signature   = runtime + ': ' + '.'.join([module, name])

        ts     = time.time()
        result = method(*args, **kw)
        te     = time.time()

        if log is not None:
            log[signature] = {}
            log[signature]['time'] = round(te - ts, 2)
            log[signature]['args'] = method_args

        return result
    return wrapper

推荐阅读