如何使用先前堆栈中的名称打印变量参数?

Posted

技术标签:

【中文标题】如何使用先前堆栈中的名称打印变量参数?【英文标题】:How do I print the variable arguments with names from previous stack? 【发布时间】:2015-12-11 23:51:46 【问题描述】:

我想定义一个日志函数,调用该函数时会显示一条消息,然后是一个或多个要打印的变量。因此,类似于以下内容:

log( "Oh no, error.", x, d)

日志的定义类似于:

def log( msg, *arg):
    # Loop through arg, printing caller's variable's name and value.

这将记录到以下文件:

Oh no, error.
    x = 5
    d =  foo: "Foo", goo: "Goo" 

这可以做到吗?我可以使用检查打印局部变量和参数,但我不知道是否可以使用前一帧的变量名遍历当前帧中的值。 (inspect.getargvalues(previousFrame) 中的locals 有名字,但也有很多其他名字。)

【问题讨论】:

如何唯一确定变量名?如果调用者在命名空间中有y 并且它的值也恰好是5 怎么办?如果调用者传递了d['foo'] 之类的东西怎么办?您是否需要任意深入地递归到调用者命名空间中的对象?如果他们传递函数调用的结果怎么办? log('message', x.bar())?这里有很多情况很难解决……尽管您可能可以检查堆栈并打印出调用者的所有局部变量。 sigh 是的,我猜你是对的 mgilson。所以我该怎么做?我必须删除这个帖子吗?或者也许这是我的一厢情愿,我只想要一个日志函数来记录我给它的变量。这根本做不到?因此,如果他们传递 5,它会打印 5 = 5。如果他们传递 y,它会打印 y = 5。如果他们传递一个对象,它会打印 object = str(object)。 @Bitdiot,为什么?它不是写得不好或组织得不好。对我个人而言,这个问题很有趣 【参考方案1】:

我认为你可以使用这样的东西:

定义

def log(msg, **kwargs):
    print(msg)
    for key, value in kwargs.items():
        print('0 = 1'.format(key,value))

定义(如果必须订购)

def log(msg, **kwargs):
    print(msg)
    for key, value in sorted(kwargs.items()):
        print('0 = 1'.format(key,value))

用法

msg='Oh no, error'
log(msg, x=5, y=6)

输出

Oh no, error
y = 6
x = 5

【讨论】:

这很好,因为它不使用任何黑魔法。还有explicit is better than implicit. 请注意,参数的顺序不一定是您所期望的...***.com/questions/8977594/… 你说得对,我这里没有考虑排序,我应该指出字典是无序的。我已经编辑了答案。【参考方案2】:

这可能很脏,有时可能无法正常工作(它在我的机器上这样做),但它似乎可以解决问题。

此外,它不需要所有这些**keargs 技巧。您只需拨打log('Message',as,many,args,as,you,want) 即可。

import inspect, gc

def log(msg,*args):
    #This gets the source code line that has to do with args
    #I mean, that calls log
    code=''.join(inspect.getframeinfo(gc.get_referrers(args)[0].f_back).code_context).strip()
    #get the arguments (except msg)
    c=code.split('log')[1].strip()
    c=c.replace('(','').replace(')','')
    c=c.split(',')[1:]
    if c[-1].endswith(';'):
        c[-1]=c[-1].replace(';','')

    for x in xrange(0,len(c)):
        print c[x],'=',args[x]


a=5; b='hello'

print 'test'

log('hello',a,b);

print 'hello'

即使log 是从另一个函数运行的,也没关系。

【讨论】:

我试过这个。看起来真的很漂亮的代码,但如果日志超过多行,它似乎会出错。我仍然喜欢它,但我认为我倾向于使用 key=val 解决方案。

以上是关于如何使用先前堆栈中的名称打印变量参数?的主要内容,如果未能解决你的问题,请参考以下文章

Inno Setup - #define 指令 - 如何使用先前定义的变量?

如何在编译时漂亮地打印模板参数的名称

在 C 语言中。如何获取先前声明的变量的左值标识符?

在 PySide 的 QTreeView 中更改时如何获取项目的先前名称

如何从 obj-c / ios 中的堆栈跟踪中获取源代码行

如何对CDH集群中的Impala打印线程堆栈