如何使用先前堆栈中的名称打印变量参数?
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 指令 - 如何使用先前定义的变量?