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

Как вы смотрите переменную в pdb

Я отлаживаю python script, и я хочу посмотреть переменную для изменения (так же, как вы можете смотреть адрес памяти в gdb). Есть ли способ сделать это?

4b9b3361

Ответ 1

Вот очень хакерский способ сделать это с помощью pdb. Эти команды можно поместить в ~/.pdbrc для автоматической загрузки каждый раз, когда вы используете pdb.

!global __currentframe, __stack; from inspect import currentframe as __currentframe, stack as __stack
!global __copy; from copy import copy as __copy
!global __Pdb; from pdb import Pdb as __Pdb
!global __pdb; __pdb = [__framerec[0].f_locals.get("pdb") or __framerec[0].f_locals.get("self") for __framerec in __stack() if (__framerec[0].f_locals.get("pdb") or __framerec[0].f_locals.get("self")).__class__ == __Pdb][-1]

alias _setup_watchpoint !global __key, __dict, __val; __key = '%1'; __dict = __currentframe().f_locals if __currentframe().f_locals.has_key(__key) else __currentframe().f_globals; __val = __copy(%1)

alias _nextwatch_internal next;; !if __dict[__key] == __val: __pdb.cmdqueue.append("_nextwatch_internal %1")
alias _stepwatch_internal step;; !if __dict[__key] == __val: __pdb.cmdqueue.append("_stepwatch_internal %1")

alias nextwatch __pdb.cmdqueue.extend(["_setup_watchpoint %1", "_nextwatch_internal"])
alias stepwatch __pdb.cmdqueue.extend(["_setup_watchpoint %1", "_stepwatch_internal"])

Это добавляет две команды: nextwatch и stepwatch, каждая из которых принимает имя переменной varname в качестве аргумента. Они сделают мелкую копию локальной переменной текущего кадра для varname, если это возможно, и продолжайте выполнение next или step соответственно до тех пор, пока это имя не укажет на изменения.

Это работает в CPython 2.7.2, но полагается на некоторые внутренние элементы pdb, поэтому он, вероятно, будет работать в другом месте.

Ответ 2

Для просмотра переменной, когда вы нажимаете точку останова, вы можете использовать команду commands. Например. печать some_variable при нажатии на точку останова №1 (канонический пример из pdb doc).

(Pdb) commands 1
(com) print some_variable
(com) end
(Pdb)

Ответ 3

Для Python 3:

вы можете использовать display функциональность pdb

Как только вы нажмете точку останова, введите

ipdb > отображение выражение

Пример:

ipdb> display instance
display instance: <AppUser: dmitry4>
ipdb> display instance.id
display instance.id: 9
ipdb> display instance.university
display instance.university: <University: @domain.com>

ipdb> display

Currently displaying:
instance.university: <University: @domain.com>
instance.id: 9
instance: <AppUser: dmitry4>
ipdb> 

как вы можете видеть, каждый раз, когда вы вводите дисплей, он печатает все ваши часы (выражения). Вы можете использовать функцию unisplay для удаления определенных часов.

Вы также можете использовать выражение pp, чтобы отпечатать выражение (очень полезно)

Ответ 4

Возможным решением является использование pdb ++:

pip install pdbpp

Затем "отметьте" объект, который вы хотите посмотреть, с помощью декоратора @pdb.break_on_setattr:

from pdb import break_on_setattr
@break_on_setattr('bar')
class Foo(object):
    pass

f = Foo()
f.bar = 42    # the program breaks here

Здесь pdb будет разбиваться на любое изменение атрибута bar на любом Foo-объекте.

Предостережения
Только вызовы базового метода __setattr__ будут вызывать точку останова. Это означает, что f.bar = 'XYZ' и setattr(f, 'XYZ') будут работать, но манипулирование объектом bar не приведет к срабатыванию точки останова:

f.bar = []
f.bar.append(7) # will NOT trigger breakpoint

f.bar = 2
f.bar += 5      # will trigger breakpoint

Примечание: @break_on_setattr не входит в стандартный pdb -модуль. pdb переопределяется/обезглавлено патчем pdbpp -пакетом.