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

Как проверить переменные после 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()
4b9b3361

Ответ 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]