2011-06-05 3 views
21

Иногда, когда я отлаживаю исключение, вы будете подняты.Как я могу увидеть детали исключения в отладчике 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?

+0

Какую версию Python вы используете? Мой не урезает. – Keith

+0

Версия 2.7.1. Обратите внимание, что оператор raise печатается целиком, поэтому на первый взгляд вы можете записать все исключение, но когда фактическое исключение «перехвачено» (я не знаю этого термина) pdb, оно усечено. – Buttons840

+0

Ну, я на самом деле написал свой собственный вариант отладчика Python, который этого не делает, а также означает автоматически вводить отладчик (использует sys.excepthook). Если вам нравится, вы можете попробовать это вместо этого. Это подпапка [debugger] (http://code.google.com/p/pycopia/source/browse/#svn%2Ftrunk%2Fdebugger). – Keith

ответ

19

pdb сохраняет тип исключения и значение в __exception__. Вы можете распечатать исключение часть TRACEBACK в 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) 

К сожалению, это не включает в себя остальную часть TRACEBACK, но вся эта информация доступна через 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 внутренних деталей и может сломаться.

+0

Спасибо за чрезвычайно полезный взлом. Удивительно, что нет нормального способа сделать что-то настолько распространенное и столь полезное. Этот хак также работает с pdb ++, поэтому я перехожу к этому через 'ipdb'. – DBedrenko

6

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

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

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

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

import traceback 
trace = traceback.format_exc() 
+2

Лучше использовать 'logging.исключение («Информативное сообщение»), которое регистрирует трассировку исключения, а также любую информацию о неудавшейся операции («информативное сообщение», которое может содержать аргументы и т. д.). Вы можете регистрироваться на любом уровне (например, DEBUG), используя 'logging.debug (..., exc_info = True)'. –

+0

Я не знал об этом - спасибо Винаю. Я обновлю свой ответ, если все в порядке? –

+0

Я использую twisted.python.log. Я мог бы использовать регистрацию, но я бы предпочел. Кроме того, попытка: повысить; кроме: ... не в моем коде, а где-то в скрученном (по крайней мере, я так думаю). Поэтому, если я собираюсь использовать журнал, мне придется изменить витой код. – Buttons840

Смежные вопросы