(Обновление от 28 мая 2016 г.) Использование RealGUD в Emacs
Для любого в Emacs этот поток показывает, как выполнить все, что описано в OP (и более), используя
- новый важный отладчик в Emacs под названием RealGUD, который может работать с любым отладчиком (в том числе
ipdb
).
- Пакет Emacs
isend-mode
.
Комбинация этих двух пакетов является чрезвычайно мощной и позволяет воссоздать в точности поведение, описанное в ОП, и сделать еще больше.
Больше информации о вики-статье RealGUD для ipdb.
Оригинальный ответ:
После того, как я попробовал много разных методов отладки Python, включая все, что упоминалось в этом потоке, один из моих предпочтительных способов отладки Python с IPython - это встроенные оболочки.
Определение пользовательской встроенной оболочки IPython:
Добавьте следующее в скрипт PYTHONPATH
, чтобы метод ipsh()
стал доступным.
import inspect
# First import the embed function
from IPython.terminal.embed import InteractiveShellEmbed
from IPython.config.loader import Config
# Configure the prompt so that I know I am in a nested (embedded) shell
cfg = Config()
prompt_config = cfg.PromptManager
prompt_config.in_template = 'N.In <\\#>: '
prompt_config.in2_template = ' .\\D.: '
prompt_config.out_template = 'N.Out<\\#>: '
# Messages displayed when I drop into and exit the shell.
banner_msg = ("\n**Nested Interpreter:\n"
"Hit Ctrl-D to exit interpreter and continue program.\n"
"Note that if you use %kill_embedded, you can fully deactivate\n"
"This embedded instance so it will never turn on again")
exit_msg = '**Leaving Nested interpreter'
# Wrap it in a function that gives me more context:
def ipsh():
ipshell = InteractiveShellEmbed(config=cfg, banner1=banner_msg, exit_msg=exit_msg)
frame = inspect.currentframe().f_back
msg = 'Stopped at {0.f_code.co_filename} at line {0.f_lineno}'.format(frame)
# Go back one level!
# This is needed because the call to ipshell is inside the function ipsh()
ipshell(msg,stack_depth=2)
Затем, когда я хочу что-то отладить в своем коде, я помещаю его ipsh()
прямо в то место, где мне нужно выполнить проверку объекта и т. Д. Например, скажем, я хочу отладитьmy_function
ниже
Используй это:
def my_function(b):
a = b
ipsh() # <- This will embed a full-fledged IPython interpreter
a = 4
и затем я вызываю my_function(2)
одним из следующих способов:
- Либо запустив программу на Python, которая вызывает эту функцию из оболочки Unix
- Или, вызвав его прямо из IPython
Независимо от того, как я вызываю его, интерпретатор останавливается на линии , что говорит ipsh()
. Как только вы закончите, вы можете это сделать, Ctrl-D
и Python возобновит выполнение (с любыми изменениями, которые вы сделали). Обратите внимание, что если вы запускаете код из обычного IPython-оболочки IPython (случай 2 выше), новая оболочка IPython будет вложена в ту, из которой вы ее вызывали, что прекрасно, но об этом следует знать. В любом случае, когда переводчик останавливается на месте ipsh
, я могу проверить значение a
(которое будет2
), посмотреть, какие функции и объекты определены, и т. Д.
Эта проблема:
Приведенное выше решение может быть использовано для остановки Python в любом месте кода, а затем для перевода в полноценный интерпретатор IPython. К сожалению, он не позволяет вам добавлять или удалять точки останова после запуска скрипта, что очень расстраивает. На мой взгляд, это единственный , что мешает IPython стать отличным инструментом отладки для Python.
Лучшее, что вы можете сделать сейчас:
Обходной путь - разместить ipsh()
a priori в разных местах, где вы хотите, чтобы интерпретатор Python запускал оболочку IPython (то есть a breakpoint
). Затем вы можете «перепрыгнуть» между различными предопределенными жестко закодированными «точками останова» Ctrl-D
, что приведет к выходу из текущей встроенной оболочки IPython и остановке снова, когда интерпретатор выполнит следующий вызовipsh()
.
Если вы идете по этому пути, один из способов выйти из «режима отладки» и игнорировать все последующие точки останова, это использовать, ipshell.dummy_mode = True
что заставит Python игнорировать любые последующие экземпляры ipshell
объекта, который мы создали выше.
!
команда, которая выполняет любую команду python в точке останова