Как проверить переменные после Traceback?
Мой Python script сбой. Чтобы отладить его, я запустил его в интерактивном режиме python -i example.py
Traceback (most recent call last):
File "example.py", line 5, in <module>
main()
File "example.py", line 3, in main
message[20]
IndexError: string index out of range
В этот момент я хотел бы проверить переменную message
. Я попробовал
>>> message
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'message' is not defined
Увы, message
не имеет значения (хотя main
is). Это расстраивает. Как проверить переменную? Есть ли более полезная версия python -i
, которая хранит то, что в области при сбое (а не на верхнем уровне)?
Код, используемый для example.py
выше. Излишне говорить, что это упрощение.
def main():
message = "hello world"
message[20]
main()
Ответы
Ответ 1
В соответствии с документами Python https://docs.python.org/3.4/library/pdb.html
pdb.py
также можно вызвать как script для отладки других скриптов. Например: python -m pdb myscript.py
. Когда вызывается как script, pdb автоматически вводит посмертную отладку, если отлаживаемая программа выходит аномально.
Это не совсем точно. Он фактически вводит отладку в первой строке.
$ python -m pdb example.py
> example.py(1)<module>()
-> def main():
Однако, если вы наберете c
, он продолжит сбой
(Pdb) c
Traceback (most recent call last):
File "C:\Python34\lib\pdb.py", line 1661, in main
pdb._runscript(mainpyfile)
File "C:\Python34\lib\pdb.py", line 1542, in _runscript
self.run(statement)
File "C:\Python34\lib\bdb.py", line 431, in run
exec(cmd, globals, locals)
File "<string>", line 1, in <module>
File "example.py", line 1, in <module>
def main():
File "example.py", line 3, in main
message[20]
IndexError: string index out of range
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> example.py(3)main()
В этот момент вы можете ввести message
для проверки переменной.
-> message[20]
(Pdb) message
'hello world'
Wahey!
Ответ 2
Чтобы отказаться от отладчика, только если есть исключение, вы можете определить пользовательский excepthook:
import sys
def excepthook(type_, value, tb):
import traceback
import pdb
traceback.print_exception(type_, value, tb)
pdb.post_mortem(tb)
sys.excepthook = excepthook
def main():
message = "hello world"
message[20]
main()
Запуск script приводит вас к pdb и в фрейме, который вызвал исключение:
% script.py
Traceback (most recent call last):
File "/home/unutbu/pybin/script.py", line 16, in <module>
main()
File "/home/unutbu/pybin/script.py", line 14, in main
message[20]
IndexError: string index out of range
> /home/unutbu/pybin/script.py(14)main()
-> message[20]
(Pdb) p message
'hello world'
(Pdb) p message[20]
*** IndexError: IndexError('string index out of range',)
(Pdb) p len(message)
11
Если определение excepthook похоже на слишком много кода, вы можете спрятать его в
полезный модуль, например utils_debug.py:
import sys
def enable_pdb():
def excepthook(type_, value, tb):
import traceback
import pdb
traceback.print_exception(type_, value, tb)
pdb.post_mortem(tb)
sys.excepthook = excepthook
а затем вам нужно будет добавить
import utils_debug as UDBG
UDBG.enable_pdb()
на ваш script.py
.
Или, если вы используете IPython, вы можете использовать % pdb magic function (что приводит к появлению ipdb
при возникновении исключения).
Непонятно, почему проверка size
в командной строке pdb дает вам имя. (Простой пример будет очень полезен.) Вы можете попытаться использовать bt
(backtrace) для проверки стека кадров. Если size
определяется в другом кадре, чем тот, в котором находится pdb
, вы можете использовать u
(вверх) чтобы перейти к кадру, где определен size
.
Ответ 3
Вы можете использовать некоторые из отладчиков Python, как указано в другом ответе, или попробуйте мой diagnostics библиотека, в которой больше подробная трассировка для вас как HTML файл:) Просто создайте каталог с именем log
рядом с файлом cheaters.py
и включите исключение с помощью строчек ниже:
from diagnostics import exception_hook
exception_hook.enable()
Ответ 4
Простой альтернативой является использование cgitb.
import cgitb; cgitb.enable(format='text')
def main():
message = "hello world"
message[20]
main()
Теперь сама трассировка печатает значение сообщения.
A problem occurred in a Python script. Here is the sequence of
function calls leading up to the error, in the order they occurred.
/home/anand/projects/python/ptb/tes.py in <module>()
4 def main():
5 message = "hello world"
6 message[20]
7
8 main()
main = <function main>
/home/anand/projects/python/ptb/tes.py in main()
4 def main():
5 message = "hello world"
6 message[20]
7
8 main()
message = 'hello world'
IndexError: string index out of range
Ответ 5
Обычно я использую модуль кода для этого типа вещей. Поймайте исключение как можно раньше и выгрузите все в интерактивную консоль прямо там.
try:
#something that might throw an error
except Exception as e:
import code
l={}
l['global_vars']=(globals()
l['local_vars']=locals()
code.InteractiveConsole(locals=l).interact()
Это запустит REPL python внутри обработчика исключений, повышенное исключение будет в local_vars ['e'], и у вас будет доступ к области, в которой был вызван блок try. Если исключение возникает внутри какой-либо другой библиотеки, вы можете изменить другой библиотечный код с помощью этого обработчика исключений, использовать переменную среды PYTHONPATH для указания python в модифицированной версии библиотеки и оставить оригинал на месте.
Ответ 6
Я очень рекомендую как ipython, так и ipdb для таких ситуаций.
Внутри оболочки ipython введите
run example.py
Когда необработанное исключение возвращает вас в оболочку ipython, вы вводите
%debug
Это поместит вас в ipdb, в точную строку кода, которая выдает необработанное исключение. Затем вы можете проверить переменные просто, оценив их так же, как и в обычной оболочке python.
Мой ответ аналогичен ответу полковника Паники, который уже был принят. Основное преимущество здесь - ipython и ipdb. Я предпочитаю эти инструменты по разным причинам, наиболее важным является то, что они позволяют заполнять вкладку имен переменных. Как только вы привыкнете к завершению табуляции, трудно жить без него, потому что это позволяет вам работать намного быстрее.
Ответ 7
use, pdb для отладки каждой строки
import pdb; pdb.set_trace()
это даст вам перерыв после каждой строки, и вы сможете отслеживать свой код
def main():
import pdb; pdb.set_trace()
message = "hello world"
message[20]
main()
когда функция main() будет вызвана, эта функция начнет работать, и вы сможете отслеживать сообщение, вы можете отлаживать его
ваш терминал будет выглядеть как
> /home/admin/dxservices/example.py(3)main()
-> message = "hello world"
(Pdb)
> /home/admin/dxservices/example.py(4)main()
-> message[20]
(Pdb) n
IndexError: 'string index out of range'
> /home/admin/dxservices/example.py(4)main()
-> message[20]