Подтвердить что ты не робот

Как печатать все значения переменных при отладке Python с помощью pdb без указания каждой переменной?

Я отлаживаю свои скрипты Python с помощью pdb, и в руководстве говорится, что я могу использовать команду p variables для печати значений указанных переменных в определенной точке. Но что, если бы у меня было много переменных, например 20 переменных, и я хотел бы отслеживать их ценность? Как распечатать все из них без указания каждого из них вручную? Возьмем, к примеру, этот script:

a = 1
b = 2
c = 3

Я могу отладить его с помощью pdb и распечатать все из них, используя p a, 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) 

Но я должен вручную указать каждую переменную. Есть ли способ распечатать все переменные сразу, без указания каждого из них?

4b9b3361

Ответ 1

pdb - полнофункциональная оболочка python, поэтому вы можете выполнять произвольные команды.

locals() и globals() будут отображать все переменные в области с их значениями.

Вы можете использовать dir(), если вас не интересуют значения.

Когда вы объявляете переменную в Python, она помещается в локальные или глобальные значения по мере необходимости, и нет возможности различать указанную вами переменную и то, что в вашей области по другой причине.

Когда вы используете dir(), вероятно, что интересующие вас переменные находятся в начале или конце этого списка. Если вы хотите получить ключ, пары значений

Фильтрация локалей() может выглядеть примерно так:

>>> 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}

Если ваш 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] != '_'}

Я добавил пример сессии pastebin

Есть несколько случаев этого промаха. И вы можете расширить его, чтобы вы могли также передавать типы. Но это должно позволить вам фильтровать все, кроме переменных, которые вы определили.

DIR()

Если вы просто хотите получить последние 20 значений, чтобы получить результат, например, >>> p var1 var2 ... varn, то вам лучше срезать dir(), как dir() [- 20:], но вы не сможете легко увидеть связь между переменными и значениями. например: "Объявлял ли я foo до или после бара?"

Если вы хотите увидеть эти отношения, вы можете попробовать что-то вроде этого, которое предполагает, что ваши переменные находятся в конце dir(). Вы можете срезать по-другому, если они в начале. Это не будет работать, если ваши переменные не будут смежными.

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

Ответ 2

Как указано в этом списке для нескольких языков:

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)

Вывод:

1
1
'value'

Маркировка каждого из них так же проста, как печать var + " equals " + eval(var).

Вы заявляете, что ваш "идеальный результат" - это результат, введя p a, b, ... , n, ...:

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

Результат выглядит так:

(1, 1, 'value')