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

Как я могу увидеть детали исключения в отладчике Python?

Иногда, когда я отлаживаю исключение, вы будете подняты.

Например, рассмотрим этот код:

def some_function():  # Pretend this function is in a library...
    # ...and deep within the library is an exception:
    raise Exception('An exception message with valuable information.')

import pdb; pdb.set_trace()
try:
    some_function()  # Pretend I am debugging from this point using pdb.
except:
    pass

Во время отладки с вызовом some_function(), если я выдаю команду next, я увижу следующие сведения об исключении, которое было поднято [и поймано]:

Exception: Exceptio...ation.',)

Здесь прямая копия/паста с терминала, в котором я работал:

> /tmp/test.py(7)<module>()
-> some_function()  # Pretend I am debugging from this point using pdb.
(Pdb) next
Exception: Exceptio...ation.',)
> /tmp/test.py(7)<module>()
-> some_function()  # Pretend I am debugging from this point using pdb.
(Pdb) 

Было бы полезно увидеть все сообщение об исключении. Как это сделать в pdb?

4b9b3361

Ответ 1

pdb хранит тип и значение исключения в __exception__. Вы можете распечатать исключающую часть трассировки в pdb с помощью:

import traceback; print "".join(traceback.format_exception_only(*__exception__))

Например:

> /tmp/test.py(7)<module>()
-> some_function()  # Pretend I am debugging from this point using pdb.
(Pdb) next
Exception: Exceptio...ation.',)
> /tmp/test.py(7)<module>()
-> some_function()  # Pretend I am debugging from this point using pdb.
(Pdb) import traceback; print "".join(traceback.format_exception_only(*__exception__))
Exception: An exception message with valuable information.

(Pdb) 

К сожалению, это не относится к остальной части трассировки, но вся эта информация доступна с помощью команды where pdb. Если вам действительно нужна полная трассировка, вы можете добавить следующее в свой файл ~/.pdbrc или вставить его в свой терминал:

!global __currentframe, __stack; from inspect import currentframe as __currentframe, stack as __stack
!global __format_exception_only, __print_stack; from traceback import format_exception_only as __format_exception_only, print_stack as __print_stack
!global __Pdb; from pdb import Pdb as __Pdb

# find the last frame on the stack with an object named "pdb" or "self" that is a pdb.Pdb object
# works for pdb called the usual way, or pdb.pm(), or pdb.set_trace()
!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 traceback __print_stack(__pdb.stack[-1][0]); print "".join(__format_exception_only(*__exception__))

Затем вы можете просто использовать новый псевдоним traceback, чтобы получить то, что вы хотите:

> /tmp/test.py(7)<module>()
-> some_function()  # Pretend I am debugging from this point using pdb.
(Pdb) next
Exception: Exceptio...ation.',)
> /tmp/test.py(7)<module>()
-> some_function()  # Pretend I am debugging from this point using pdb.
(Pdb) traceback
  File "test.py", line 7, in <module>
    some_function()  # Pretend I am debugging from this point using pdb.
  File "test.py", line 3, in some_function
    raise Exception('An exception message with valuable information.')
Exception: An exception message with valuable information.

(Pdb) 

Предупреждение: все это зависит от недокументированных внутренних объектов pdb и bdb и, скорее всего, сломается.

Ответ 2

Отладчик python не "прерывает исключение" - что может быть довольно неприятным, если вы привыкли к этой функции. Таким образом, я принимаю политику регистрации трассировочных трасс и отработки оттуда.

import logging
try:
    raise Exception('An exception message with valuable information.')
except:
    logging.exception('Error in test code')

Если вы используете хорошую среду IDE (например, Eclipse с pydev), записи журнала для stacktrace сделаны в гиперссылки, которые переходят прямо в соответствующую позицию в коде.

Вы можете сбросить трассировку стека в любой точке вашего кода, импортируя трассировку

import traceback
trace = traceback.format_exc()