(2016年5月28日更新)在Emacs中使用RealGUD
对于Emacs中的任何人,此线程都说明了如何使用
- Emacs中一个称为RealGUD的新的重要调试器,可以与任何调试器(包括
ipdb
)一起使用。
- Emacs软件包
isend-mode
。
这两个软件包的组合非常强大,可以使它们完全重新创建OP中描述的行为,甚至可以做更多的事情。
有关RealGUD for ipdb 的Wiki文章的更多信息。
原始答案:
在尝试了多种不同的调试Python方法(包括本线程中提到的所有内容)之后,我使用IPython调试Python的首选方法之一是使用嵌入式外壳程序。
定义定制的嵌入式IPython Shell:
将以下内容添加到脚本中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)
以下列方式之一调用:
- 通过运行从Unix Shell调用此函数的Python程序
- 或直接从IPython调用
不管我如何调用它,解释器都会停在所说的行ipsh()
。完成后,您可以执行操作Ctrl-D
,Python将恢复执行(使用您所做的任何变量更新)。请注意,如果您从常规IPython IPython Shell(上面的案例2)运行代码,那么新的IPython Shell将嵌套在您从中调用它的外壳内,这很好,但是请注意。无论哪种方式,一旦解释器停在的位置ipsh
,我都可以检查a
(2
)的值,查看定义了哪些函数和对象,等等。
问题:
上面的解决方案可以使Python在代码中所需的任何位置停止,然后将您带入完整的IPython解释器。不幸的是,调用脚本后,它不允许您添加或删除断点,这非常令人沮丧。在我看来,这是阻止IPython成为Python出色的调试工具的唯一原因。
您目前可以做的最好的事情是:
一种解决方法是ipsh()
在要Python解释程序启动IPython Shell的不同位置(即breakpoint
)放置先验先验。然后,您可以使用以下命令在不同的预定义,硬编码的“断点”之间“跳转”Ctrl-D
,这将退出当前的嵌入式IPython shell,并且每当解释器单击下一个调用时再次停止ipsh()
。
如果走这条路线,退出“调试模式”并忽略所有后续断点的一种方法是使用ipshell.dummy_mode = True
,这将使Python忽略ipshell
我们在上面创建的对象的任何后续实例化。
!
在断点执行任何python命令的命令