据我所读,在Python中有两种调试代码的方法:
pdb或ipdb )。这支持诸如c for continue、n for step-over、s for step-into等命令,但您不能直接访问IPython shell,这对于对象检查非常有用。from IPython import embed,然后在代码中使用embed()。当您的程序/脚本命中embed()语句时,您将被丢弃到IPython shell中。这允许使用所有IPython工具全面检查对象和测试Python代码。然而,在使用step-by-step时,您不能再使用方便的键盘快捷键通过代码进行embed()了。有没有办法把这两个世界的优点结合起来?也就是说。
IPython调试,如MATLAB中所示:
这种类型的“增强调试”的例子可以在MATLAB中找到,用户总是可以完全访问MATLAB引擎/shell,而且她仍然可以通过自己的代码进行,定义条件断点等。从我与其他用户讨论过的情况来看,这是人们在从MATLAB迁移到IPython时最缺少的调试功能。
Emacs和其他编辑器中的IPython调试:
我不想让这个问题过于具体,但我主要是在Emacs工作,所以我想知道是否有任何方法将这个功能引入其中。理想情况下,、Emacs (或编辑器)将允许程序员在代码的任何位置设置断点,并与解释器或调试器通信,使其停止在您选择的位置,并在该位置将其带到一个完整的IPython解释器中。
发布于 2017-04-14 14:14:04
您可以使用IPython的魔术。只需在%pdb中调用IPython,当发生错误时,将自动丢弃到ipdb。虽然您没有立即采取步骤,但之后您将进入ipdb。
这使得调试单个函数变得容易,因为您只需用%load加载一个文件,然后运行一个函数。您可以在正确的位置使用assert强制出错。
%pdb是一种线魔法。叫它%pdb on,%pdb 1,%pdb off或%pdb 0。如果调用时不带任何参数,则充当切换。
发布于 2013-06-03 10:46:18
那么ipdb.set_trace()呢?在您的代码中:
import ipdb; ipdb.set_trace()
更新:现在在Python3.7中,我们可以编写breakpoint()。它的工作原理相同,但它也服从PYTHONBREAKPOINT环境变量。这个特性来自于这个PEP。
这允许对您的代码进行全面检查,并且您可以访问诸如c (继续)、n (执行下一行)、s (在点处进入方法)等命令。
见ipdb回购和命令列表。IPython现在被称为(编辑:木星的一部分)。
ps:注意,ipdb命令优先于python代码。因此,为了编写list(foo),您需要print(list(foo)),或!list(foo)。
另外,如果您喜欢ipython提示符(它的emacs和vim模式、历史、完成、…)您的项目很容易获得相同的结果,因为它是基于python提示工具包的。
发布于 2014-04-30 12:28:48
(2016年5月28日更新)在Emacs中使用RealGUD
对于Emacs中的任何人,这条线将展示如何使用以下方法完成OP中描述的所有内容(以及更多)
ipdb)一起操作。isend-mode。这两个包的组合非常强大,允许您精确地重新创建OP中描述的行为,并进行更多的操作。
关于维基文章 of RealGUD for ipdb的更多信息。
原来的答案:
在尝试了许多不同的方法来调试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()放在我需要进行对象检查的位置,例如,假设我想在下面调试my_function
使用它:
def my_function(b):
a = b
ipsh() # <- This will embed a full-fledged IPython interpreter
a = 4然后,我以下列方式之一调用my_function(2):
不管我如何调用它,解释器都会停在写着ipsh()的行上。一旦完成,您就可以执行Ctrl-D和Python将继续执行(使用您所做的任何变量更新)。注意,如果您从常规的IPython运行代码-- IPython shell (上面的案例2)--那么新的IPython shell将是调用它的IPython shell中的嵌套,这是非常好的,但是很好地了解它。另外,一旦解释器在ipsh的位置停止,我就可以检查a的值(即2),查看定义了哪些函数和对象等等。
问题是:
上面的解决方案可以用于让Python在代码中的任何位置停止,然后将您放到成熟的IPython解释器中。不幸的是,它不允许您在调用脚本后添加或删除断点,这是非常令人沮丧的。在我看来,这是唯一的,它阻止了IPython成为一个很好的调试工具。
现在你能做的最好的事情是:
解决方法是将ipsh()放在您希望Python解释器启动IPython外壳(即breakpoint)的不同位置。然后,您可以使用Ctrl-D在不同的预定义、硬编码的“断点”之间“跳转”,这将退出当前的嵌入式IPython外壳,并在解释器执行下一个对ipsh()的调用时再次停止。
如果您使用此路径,退出“调试模式”并忽略所有后续断点的一种方法是使用ipshell.dummy_mode = True,这将使Python忽略我们前面创建的ipshell对象的任何后续实例化。
https://stackoverflow.com/questions/16867347
复制相似问题