如何以可重用的方式记录Python函数的参数?

4 投票
1 回答
3468 浏览
提问于 2025-04-18 08:12

我发现自己写这样的代码已经好几次了:

def my_func(a, b, *args, **kwargs):
    saved_args = locals() # Learned about this from http://stackoverflow.com/a/3137022/2829764
    local_var = "This is some other local var that I don't want to log"
    try:
        a/b
    except Exception as e:
        logging.exception("Oh no! My args were: " + str(saved_args))
        raise

运行 my_func(1, 0, "spam", "ham", my_kwarg="eggs") 会在错误输出中显示以下内容:

ERROR:root:Oh no! My args were: {'a': 1, 'args': (u'spam', u'ham'), 'b': 0, 'kwargs': {'my_kwarg': u'eggs'}}
Traceback (most recent call last):
  File "/Users/kuzzooroo/Desktop/question.py", line 17, in my_func
    a/b
ZeroDivisionError: division by zero

我的问题是,我能不能写一些可重用的代码,这样就不需要在函数开头保存本地变量(locals())了?而且能不能用一种优雅的Python方式来实现?

补充说明:根据@mtik00的建议,我希望能有一种方法在my_func内部访问保存的参数(saved_args),这样我就可以做一些其他的事情,而不仅仅是记录未捕获的异常(也许我想在my_func中捕获异常,记录错误,然后继续执行)。

1 个回答

8

装饰器就是你需要的东西。这里有个例子:

import logging
from functools import wraps


def arg_logger(func):

    @wraps(func)
    def new_func(*args, **kwargs):
        saved_args = locals()
        try:
            return func(*args, **kwargs)
        except:
            logging.exception("Oh no! My args were: " + str(saved_args))
            raise

    return new_func


@arg_logger
def func(arg1, arg2):
    return 1 / 0

if __name__ == '__main__':
    func(1, 2)

在这里,我把 arg_logger() 当作一个 装饰器 来使用。你可以把这个装饰器应用到任何你想要添加这种新功能的函数上。

关于装饰器的讨论可以在 这里 找到。

撰写回答