【问题标题】:Record variables values in Python (without decorators)在 Python 中记录变量值(没有装饰器)
【发布时间】:2022-08-19 17:51:53
【问题描述】:

有没有办法在 Python 中记录程序的变量和参数,而无需手动装饰其中的函数? 例如,给定以下代码:

def get_b(a):
    # do something with a
    # ...

    b = 3
    return b

def get_a():
    a = 2
    return a

def foo():
    a = get_a()
    b = get_b(a)
    return a, b

if __name__ \'__main__\':
    a, b = foo()

我想知道那次特定运行中的参数/变量的值是什么。也许是这样的:

function get_a:
variables: \"a\" = 2

function get_b:
parameters: \"a\" = 2
variables: \"b\" = 3

有没有办法“记录”所有这些信息?

  • 您可以选择修改功能吗?
  • 我不喜欢,因为我有一个庞大的代码库。如果可能的话,我想在不修改底层代码的情况下记录执行中的变量。

标签: python


【解决方案1】:

在模块的全局范围内添加以下代码。它会给你所要求的。该代码使用sys.setprofile。请务必查阅文档。 setprofile 不适用于日常使用。它可能会导致性能下降,并且我的示例代码在多线程程序中不起作用。

我们正在做的是每个调用或返回函数的语句,我们的配置文件函数被调用。在此配置文件函数中,我们可以访问事件类型(调用、返回)和帧信息对象。从框架信息对象中,我们可以访问调用或返回函数的命名空间中的所有变量。从这些局部变量中,我们过滤那些作为参数传递给相应函数的变量。就是这样。

import inspect

def profile(frame, event, arg):
    if (fn_name := frame.f_code.co_name) != '<module>' and event == 'return':
        args_info = inspect.getargvalues(frame)
        args_locals = args_info.locals
        params = [f'{arg}={args_locals.pop(arg)}' for arg in args_info.args]
        if not params:
            params = ''
        else:
            params = ', '.join(params)
        if args_locals:
            args_locals = ', '.join([f'{k}={v}' for (k, v) in args_locals.items()])

        print(f'Function {fn_name}:')
        print(f'    params: {params}')
        print(f'    locals: {args_locals}')

    return profile


sys.setprofile(profile)

输出:

Function get_a:
    params: 
    locals: a=2
Function get_b:
    params: a=2
    locals: b=3
Function foo:
    params: 
    locals: a=2, b=3

推荐阅读:What cool hacks can be done using sys.settrace?

【讨论】:

    猜你喜欢
    • 2020-07-24
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    • 2012-11-24
    • 2020-10-09
    • 2023-03-23
    • 2019-05-07
    • 2017-12-24
    相关资源
    最近更新 更多