我正在尝试编写一个函数来帮助我进行调试。我不想时不时地插入几个print语句,而是插入一个一行调试语句。我期望完成的是这样的函数可以被重用:我想在几个函数中使用它,以便打印不同的变量集。
我特别想做的是:
def _debugFunction(var_list):
global debug_flag
if debug_flag:
print 'START DEBUGGING:'
< magic code >
print 'END DEBUGGING'
def foo_function(n):
x = 1
y = 2
z = 'string'
debugFunction([x, y, z])
return x + y因此,当我设置debug_flag = True并调用foo时,输出是:
START DEBUGGING:
x = 1
y = 2
z = 'string'
END DEBUGGING
3然后,如果设置debug_flag = False并调用foo,输出是:
3为此,我需要在运行时获取作为参数传递给debugFunction()的变量的名称,并将其与值一起打印出来。
我搜索过其他的帖子,却找不到直接的答案。
How to get a variable name as a string in Python?
retrieving a variable's name in python at runtime?
据我所理解,人们被告知要使用日志模块。我看过它,并试图实现它中的一小部分,但我还无法记录任何东西(但不会放弃)。
我还读到人们会被指向__dict()__、vars()或dir(),但不知道如何使用它们。此外:如果我试图将它们应用于我的变量,我只会得到错误,或者(对我来说)没有意义的输出。
有办法这样做吗?这做法太糟糕了吗?如果是这样的话:什么是好做法?
PS:也许没有必要浪费精力来实现这一点,而是花时间了解如何正确地使用日志模块。
发布于 2014-07-24 18:55:09
我还读到有人被指向dict()、vars()或dir(),但不知道如何使用它们。
你试过看这些功能的文档吗?例如,vars
…没有任何参数,vars()的行为就像局部变量()。注意,由于对局部变量字典的更新被忽略,因此局部变量字典只对读取有用。
好的,那么locals是做什么的?查看docs:它为您提供了一个字典,它将函数中的每个本地名称映射为其值。因此,如果不想同时传递名称和值,请传递locals()字典和名称:
def foo_function(n):
x = 1
y = 2
z = 'string'
debugFunction(locals(), ['x', 'y', 'z'])
return x + y
def _debugFunction(localdict, var_list):
global debug_flag
if debug_flag:
print 'START DEBUGGING:'
for name in var_list:
print('{}: {}'.format(name, localdict[name]))
print 'END DEBUGGING'就这样。不过,我可能会稍微修改接口,以使用*var_list,或者更简单地更改可以split的字符串,并且,为了简化在简单情况下的使用,默认情况下打印所有局部变量:
def _debugFunction(localdict, var_list=''):
var_list = var_list.split()
if not var_list:
var_list = localdict.keys()现在你可以这样做了:
_debugFunction(locals(), 'x y z')或者只是:
_debugFunction(locals())发布于 2014-07-24 19:11:41
您想要的几乎是可能的,只适用于CPython…但是一个非常非常糟糕的主意。下面是代码:
def _debugFunction(values):
caller = sys._getframe(1)
revlocals = {value: key for key, value in caller.f_locals.items()}
for value in values:
print('{}: {}'.format(revlocals[value], value))这里的第一个问题是它只处理本地的,而不是全局的。这很容易修复,例如,ChainMap或者仅仅是dict.update。
第二个问题是,如果传递一个不绑定任何名称的值(比如,_debugFunction([2]),它将引发异常)。你可以用revlocals.get(value, '<constant>')来解决这个问题。
第三个问题是,如果传递一个绑定到两个或多个名称的值,它将任意选择一个。因此,这段代码将打印两次'x: 0‘:
x = y = 0
_debugFunction([x, y])您甚至可以通过查看框架的f_code和f_lasti来找到它在调用函数时正在执行的字节码,从而可以修复该字节码,从该字节码中可以知道每个参数来自何处--例如,如果第一个参数来自LOAD_FAST 1,那么它的名称是f.f_code.co_varnames[1]。(或者,您可以将其解压缩到AST,这可能更容易处理,但这需要第三方代码。)这甚至更加困难--它依赖于CPython编译器从未以任何方式优化传递函数调用的参数这一点几乎总是正确的,尽管我认为在Python3.4中有两种边缘情况。我将留下代码,并发现和处理这些边缘案例,作为读者的练习。
当然,将其转过来,传递名称,并使用框架哈克来获取与这些名称相关的值,这要简单得多。这仍然是个坏主意,也很烦人,但我认为我应该拒绝展示代码:
def _debugFunction(names):
f = sys._getframe(1)
values = collections.ChainMap(f.f_locals, f.f_globals)
for name in names.split():
print('{}: {}'.format(name, values.get(name, '<undefined>')))
a = 0
def test(b):
b = c = 1
d = 'abc'
_debugFunction('a b c d e')https://stackoverflow.com/questions/24941504
复制相似问题