Step-by-step debugging with IPython
根据我所读到的,有两种方法可以调试Python中的代码:
使用传统的调试器,如
pdb 或ipdb 。它支持诸如continue 的c ,step-over 的n ,s 的step-into 等命令,但您不能直接访问ipython外壳,这对于对象检查非常有用。通过在代码中嵌入ipython外壳来使用ipython。您可以执行
from ipython import embed ,然后在代码中使用embed() 。当程序/脚本命中embed() 语句时,您将被放入ipython shell中。这允许使用所有的ipython goodies对对象进行全面检查和测试python代码。但是,当使用embed() 时,您不能再使用方便的键盘快捷键逐步地浏览代码了。
有没有办法把两个世界的精华结合起来?即。
在matlab中进行ipython调试:
在Matlab中可以找到这种"增强调试"的一个例子,用户总是可以完全访问Matlab引擎/shell,而且她仍然可以一步一步地通过她的代码,定义条件断点等。根据我与其他用户讨论的内容,这是从Matlab迁移时人们最怀念的调试功能。伊普敦。
Emacs和其他编辑器中的ipython调试:我不想让问题过于具体,但我主要是在Emacs中工作,所以我想知道是否有任何方法可以将此功能引入其中。理想情况下,Emacs(或编辑器)将允许程序员在代码的任何位置设置断点,并与解释器或调试器通信,使其在您选择的位置停止,并在该位置使用完整的IPython解释器。
ipdb.set_trace()怎么样?在您的代码中:
埃多克斯1〔3〕
更新:现在在python 3.7中,我们可以编写
这允许对代码进行全面检查,并且您可以访问诸如EDOCX1(continue)、EDOCX1(execute next line)、EDOCX1(step into the method at point)等命令。
请参阅ipdb repo和命令列表。伊普利顿现在被称为朱彼特。
注意,ipdb命令优先于python代码。所以,为了写
另外,如果您喜欢ipython提示(它的emacs和vim模式、历史、完成等等),那么很容易为您的项目获得相同的结果,因为它是基于python提示工具包的。
(2016年5月28日更新)在emacs中使用realgud
对于Emacs中的任何人,此线程将演示如何使用
这两个包的组合是非常强大的,它允许您准确地重新创建OP中描述的行为,并执行更多操作。
有关IPDB的realgud wiki文章的更多信息。
原始答案:在尝试了许多调试Python的不同方法(包括本线程中提到的所有方法)之后,我使用IPython调试Python的首选方法之一是使用嵌入式shell。
定义自定义嵌入的IPython外壳:在脚本中添加以下内容到您的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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 = (" **Nested Interpreter: " "Hit Ctrl-D to exit interpreter and continue program. " "Note that if you use %kill_embedded, you can fully deactivate " "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) |
然后,每当我想在代码中调试某个东西时,我就将
1 2 3 4 | def my_function(b): a = b ipsh() # <- This will embed a full-fledged IPython interpreter a = 4 |
号
然后我用以下方法之一调用
不管我如何调用它,解释器都会停在说
上面的解决方案可以用于让python在代码中的任何地方停止,然后将您放入一个成熟的ipython解释器中。不幸的是,它不允许您在调用脚本后添加或删除断点,这非常令人沮丧。在我看来,这是唯一一件阻止ipython成为Python调试工具的事情。
你现在能做的最好的:解决方法是将
如果您走这条路线,退出"调试模式"并忽略所有后续断点的一种方法是使用
还没有人提到过伊普顿的
这使得调试单个函数变得容易,因为您只需使用
您可以从pudb启动ipython会话,然后根据需要返回到调试会话。
顺便说一句,IPDB在幕后使用IPython,实际上您可以使用IPython功能,例如制表完成和magic命令(其中一个以
另外,与emacs>=24.3捆绑在一起的python.el具有很好的IPDB支持。
看来@gaborous答案中的方法已被否决。
新方法似乎是:
1 2 3 4 5 | from IPython.core import debugger debug = debugger.Pdb().set_trace def buggy_method(): debug() |
为"!"添加前缀在pdb中键入的命令符号似乎与在ipython shell中执行某些操作具有相同的效果。这适用于访问某个函数的帮助,甚至是变量名。也许这会在某种程度上帮助你。例如,
1 2 | ipdb> help(numpy.transpose) *** No help on (numpy.transpose) |
但是!帮助(numpy.transfe)将在numpy.transfe上提供预期的帮助页。同样,对于变量名,假设您有一个变量l,在pdb中键入"l"会列出代码,但是!l打印l的值。
你试过这个提示吗?
Or better still, use ipython, and call:
1 from IPython.Debugger import Tracer; debug_here = Tracer()then you can just use
1 debug_here()whenever you want to set a breakpoint
号
正确、简单、酷、准确的答案是使用带有-d标志的%run宏。
1 2 3 4 5 6 7 | In [4]: run -d myscript.py NOTE: Enter 'c' at the ipdb> prompt to continue execution. > /cygdrive/c/Users/mycodefolder/myscript.py(4)<module>() 2 3 ----> 4 a=1 5 b=2 |
一种选择是使用类似于IDE的Spyder,它应该允许您在调试时与代码交互(实际上使用的是IPython控制台)。事实上,Spyder非常类似于matlab,我认为这是有意的。这包括变量检查程序、变量编辑、对文档的内置访问等。
PYZO IDE的功能与OP要求的功能相似。您不必在调试模式下启动。与matlab类似,命令在shell中执行。当您在一些源代码行中设置断点时,IDE会在那里停止执行,您也可以调试和发出常规的ipython命令。
不过,似乎进入这一步(还没有?)除非您设置了另一个断点,否则工作良好(即在一行中停止,然后进入另一个函数)。
不过,来自Matlab,这似乎是我找到的最佳解决方案。
如果在embed()控制台中键入exit(),代码将继续并转到下一个embed()行。
在python 3.2中,您有
从Emacs的ipython shell内部运行,并通过pdb.set_trace()设置断点。
使用python-mode.el、m-x ipython ret等进行检查。