Я отлаживаю python script, и я хочу посмотреть переменную для изменения (так же, как вы можете смотреть адрес памяти в gdb). Есть ли способ сделать это?
Как вы смотрите переменную в pdb
Ответ 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
-пакетом.