Ответ 1
Обновление для IPython v0.13:
import sys
from IPython.core import ultratb
sys.excepthook = ultratb.FormattedTB(mode='Verbose',
color_scheme='Linux', call_pdb=1)
Есть ли способ запустить оболочку или приглашение IPython, когда моя программа запускает строку, которая вызывает исключение?
В основном меня интересует контекст, переменные, в области (и подкосе), где было создано исключение. Что-то вроде отладки Visual Studio, когда исключение выбрасывается, но не улавливается кем-либо, Visual Studio останавливается и дает мне стек вызовов и переменные, присутствующие на каждом уровне.
Как вы думаете, есть ли способ получить что-то подобное с помощью IPython?
EDIT: Параметр -pdb
при запуске IPython, похоже, не делает то, что я хочу (или, может быть, я не знаю, как правильно его использовать, что вполне возможно). Я запускаю следующий script:
def func():
z = 2
g = 'b'
raise NameError("This error will not be caught, but IPython still"
"won't summon pdb, and I won't be able to consult"
"the z or g variables.")
x = 1
y = 'a'
func()
Используя команду:
ipython -pdb exceptionTest.py
Что прекращает выполнение при возникновении ошибки, но приносит мне приглашение IPython, где у меня есть доступ к глобальным переменным script, но не к локальным переменным функции func. pdb
вызывается только при прямом вводе команды в ipython, которая вызывает ошибку, т.е. raise NameError("This, sent from the IPython prompt, will trigger pdb.")
.
Мне не обязательно использовать pdb
, я просто хочу иметь доступ к переменным внутри func
.
РЕДАКТИРОВАТЬ 2:. В настоящее время IPython -pdb
теперь работает так, как я хочу. Это означает, что когда я создаю исключение, я могу вернуться в область func
и без проблем прочитать его переменные z
и g
. Даже не устанавливая параметр -pdb
, можно запустить IPython в интерактивном режиме, а затем вызвать волшебную функцию %debug
после выхода программы с ошибкой - это также приведет вас к интерактивной подсказке ipdb со всеми доступными доступными областями.
Обновление для IPython v0.13:
import sys
from IPython.core import ultratb
sys.excepthook = ultratb.FormattedTB(mode='Verbose',
color_scheme='Linux', call_pdb=1)
Doing:
ipython --pdb -c "%run exceptionTest.py"
запускает script после инициализации IPython и вы попадаете в обычную среду IPython + pdb.
ipdb интегрирует функции IPython в pdb. Я использую следующий код, чтобы выбросить мои приложения в отладчик IPython после непредвиденного исключения.
import sys, ipdb, traceback
def info(type, value, tb):
traceback.print_exception(type, value, tb)
print
ipdb.pm()
sys.excepthook = info
@snapshoe ответ не работает с новыми версиями IPython.
Это однако:
import sys
from IPython import embed
def excepthook(type, value, traceback):
embed()
sys.excepthook = excepthook
Вы можете сделать что-то вроде следующего:
import sys
from IPython.Shell import IPShellEmbed
ipshell = IPShellEmbed()
def excepthook(type, value, traceback):
ipshell()
sys.excepthook = excepthook
Смотрите sys.excepthook и Внедрение IPython.
Эта справочная страница говорит, что iPython имеет опцию --[no]pdb
, которая должна быть передана в командной строке, чтобы запустить iPython для неперехваченных исключений. Вы ищете еще?
EDIT:
python -m pdb pythonscript.py
может запускать pdb. Однако не уверен в том, что с iPython. Если вы ищете трассировку стека и общую посмертную информацию об аномальном выходе программы, это должно сработать.
@Adam работает как шарм, за исключением того, что IPython загружается немного медленно (800 мс на моей машине). Здесь у меня есть трюк, чтобы сделать нагрузку ленивой.
class ExceptionHook:
instance = None
def __call__(self, *args, **kwargs):
if self.instance is None:
from IPython.core import ultratb
self.instance = ultratb.FormattedTB(mode='Verbose',
color_scheme='Linux', call_pdb=1)
return self.instance(*args, **kwargs)
sys.excepthook = ExceptionHook()
Теперь нам не нужно ждать в самом начале. Только при сбое программы будет вызван IPython.
Вы можете попробовать следующее:
from ipdb import launch_ipdb_on_exception
def main():
with launch_ipdb_on_exception():
# The rest of the code goes here.
[...]
Действительно ли вы хотите открыть сеанс pdb во всех точках исключения? (как я думаю, сеанс pdb, открытый из ipython, такой же, как и открытый в нормальной оболочке). Если это случай, вот трюк: http://code.activestate.com/recipes/65287-automatically-start-the-debugger-on-an-exception/
Если вы хотите как получить трассировку, так и открыть оболочку IPython со средой в точке исключения:
def exceptHook(*args):
'''A routine to be called when an exception occurs. It prints the traceback
with fancy formatting and then calls an IPython shell with the environment
of the exception location.
'''
from IPython.core import ultratb
ultratb.FormattedTB(call_pdb=False,color_scheme='LightBG')(*args)
from IPython.terminal.embed import InteractiveShellEmbed
import inspect
frame = inspect.getinnerframes(args[2])[-1][0]
msg = 'Entering IPython console at {0.f_code.co_filename} at line {0.f_lineno}'.format(frame)
savehook = sys.excepthook # save the exception hook
InteractiveShellEmbed()(msg,local_ns=frame.f_locals,global_ns=frame.f_globals)
sys.excepthook = savehook # reset IPython change to the exception hook
import sys
sys.excepthook = exceptHook
Обратите внимание, что необходимо вытащить, чем информацию о пространстве имен из последнего кадра, на который ссылается трассировка (arg [2])