使用pdb调试Python时如何打印所有变量值,而不指定每个变量?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21961693/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 23:58:09  来源:igfitidea点击:

How to print all variables values when debugging Python with pdb, without specifying each variable?

pythondebuggingpdb

提问by renatov

I'm debugging my Python scripts using pdband the manual says I can use p variablescommand to print the values of the specified variables at a certain point. But what if I had lots of variables, like 20 variables, and I would like to track the value of all of them? How do I print all of them without specifying each one manually? Take for example this script:

我正在使用pdb调试我的 Python 脚本,手册说我可以使用p variables命令在某个点打印指定变量的值。但是如果我有很多变量,比如 20 个变量,我想跟踪所有变量的值怎么办?如何在不手动指定每一个的情况下打印所有这些?以这个脚本为例:

a = 1
b = 2
c = 3

I can debug it with pdb and print all of them using p a, b, clike this:

我可以使用 pdb 调试它并使用pa, b, c打印所有它们如下所示:

$ python -m pdb test.py 
> /media/test.py(1)<module>()
-> a = 1
(Pdb) n
> /media/test.py(2)<module>()
-> b = 2
(Pdb) n
> /media/test.py(3)<module>()
(Pdb) n
--Return--
> /media/test.py(3)<module>()->None
-> c = 3
(Pdb) p a, b, c
(1, 2, 3)
(Pdb) 

But I have to manually specify each variable. Is there a way of print all variables at once, without specifying each one of them?

但我必须手动指定每个变量。有没有办法一次打印所有变量,而不指定每个变量?

采纳答案by munk

pdb is a fully featured python shell, so you can execute arbitrary commands.

pdb 是一个功能齐全的python shell,因此您可以执行任意命令。

locals()and globals()will display all the variables in scope with their values.

locals()并且globals()将显示范围内的所有变量与他们的价值观。

You can use dir()if you're not interested in the values.

dir()如果您对这些值不感兴趣,则可以使用。

When you declare a variable in Python, it's put into locals or globals as appropriate, and there's no way to distinguish a variable you defined and something that's in your scope for another reason.

当您在 Python 中声明一个变量时,它会被适当地放入局部变量或全局变量中,并且由于其他原因无法区分您定义的变量和您范围内的变量。

When you use dir(), it's likely that the variables you're interested in are at the beginning or end of that list. If you want to get the key, value pairs

当您使用 dir() 时,您感兴趣的变量很可能位于该列表的开头或结尾。如果要获取键值对

Filtering locals()might look something like:

过滤 locals()可能类似于:

>>> x = 10
>>> y = 20
>>> {k: v for k,v in locals().iteritems() if '__' not in k and 'pdb' not in k}
{'y': 20, 'x': 10}

If your locals() is a real mess, you'll need something a little more heavy handed. You can put the following function in a module on your pythonpath and import it during your debugging session.

如果你的 locals() 真的一团糟,你需要一些更严厉的东西。您可以将以下函数放在 pythonpath 上的模块中,并在调试会话期间导入它。

def debug_nice(locals_dict, keys=[]):
    globals()['types'] = `__import__`('types')
    exclude_keys = ['copyright', 'credits', 'False', 
                    'True', 'None', 'Ellipsis', 'quit']
    exclude_valuetypes = [types.BuiltinFunctionType,
                          types.BuiltinMethodType,
                          types.ModuleType,
                          types.TypeType,
                          types.FunctionType]
    return {k: v for k,v in locals_dict.iteritems() if not
               (k in keys or
                k in exclude_keys or
                type(v) in exclude_valuetypes) and
               k[0] != '_'}

I've added an example session on pastebin

我在pastebin上添加了一个示例会话

There are a couple of cases this misses. And you might want to extend it to allow you to pass in types too. But it should let you filter most everything but the variables you defined.

有几种情况会错过。并且您可能想要扩展它以允许您也传递类型。但它应该可以让您过滤除您定义的变量之外的所有内容。

dir()

目录()

If you just want the last 20 values so you get output like >>> p var1 var2 ... varnwould give you, then you're better off slicing dir() like dir()[-20:], but you won't easily see the relationship between the variables and values. eg: "Did I declare foo before or after bar?"

如果你只想要最后 20 个值,所以你得到像>>> p var1 var2 ... varn会给你的输出,那么你最好像 dir()[-20:] 那样对 dir() 进行切片,但是你不会轻易看到变量和值。例如:“我是在 bar 之前还是之后声明了 foo?”

If you want to see that relationship, you can try something like this, which assumes that your variables are at the end of dir(). You can slice differently if they're at the beginning. This won't work well if your variables aren't contiguous.

如果你想看到这种关系,你可以尝试这样的事情,它假设你的变量在 dir() 的末尾。如果它们在开头,您可以进行不同的切片。如果您的变量不连续,这将无法正常工作。

>>> zip(dir(), [eval(var) for var in dir()])[-4:]
[('a', 10), ('var', 'var'), ('x', 30), ('y', 50)]

回答by OJFord

As given in this list for multiple languages:

如此列表中针对多种语言所给出的:

a = 1
b = 1
n = 'value'
#dir() == ['__builtins__', '__doc__', '__name__', '__package__', 'a', 'b', 'n']
for var in dir()[4:]:
    value_of_var = eval(var)
    print(value_of_var)

Output:

输出:

1
1
'value'

Labelling each one is as simple as printing var + " equals " + eval(var).

给每一个贴上标签就像打印一样简单var + " equals " + eval(var)

You state your "ideal output" is exactly the result as typing p a, b, ... , n, ...:

您声明您的“理想输出”正是键入的结果p a, b, ... , n, ...

vars = []
for var in dir()[4:-1]
    vars.append(var)
print(tuple(vars))

Output looks like:

输出看起来像:

(1, 1, 'value')