(2016年5月28日更新)在Emacs中使用RealGUD
对于Emacs中的任何人,this thread演示如何使用Emacs中的一个新的重要调试器称为RealGUD,它可以与任何调试器(包括ipdb)一起操作。
Emacs包isend-mode。
这两个包的组合是非常强大的,允许一个人重新创建操作中描述的行为,甚至可以做更多的事情。
关于ipdb的RealGUD的the wiki article的更多信息。
原始答案:
在尝试了许多调试Python的不同方法(包括这个线程中提到的所有方法)之后,使用IPython调试Python的首选方法之一是使用嵌入式shell。
定义自定义嵌入式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()放在需要进行对象检查的位置,等等
使用:def my_function(b):
a = b
ipsh() # <- This will embed a full-fledged IPython interpreter
a = 4
然后我用以下方法之一调用my_function(2):或者通过运行一个Python程序从Unix shell调用这个函数
或者直接从IPython调用它
不管我如何调用它,解释器都会停在表示ipsh()的行上。完成后,可以执行Ctrl-D,Python将恢复执行(使用您所做的任何变量更新)。注意,如果从IPython shell的常规IPython运行代码(上面的情况2),新的IPython shell将被嵌套在调用它的那个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对象的任何后续实例化。