首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用IPython一步一步地调试

用IPython一步一步地调试
EN

Stack Overflow用户
提问于 2013-05-31 23:21:04
回答 15查看 122.3K关注 0票数 198

据我所读,在Python中有两种调试代码的方法:

  • 使用传统调试器(如pdbipdb )。这支持诸如c for continuen for step-overs for step-into等命令,但您不能直接访问IPython shell,这对于对象检查非常有用。
  • 在代码中使用 IPython by 嵌入 嵌入IPython shell。您可以执行from IPython import embed,然后在代码中使用embed()。当您的程序/脚本命中embed()语句时,您将被丢弃到IPython shell中。这允许使用所有IPython工具全面检查对象和测试Python代码。然而,在使用step-by-step时,您不能再使用方便的键盘快捷键通过代码进行embed()了。

有没有办法把这两个世界的优点结合起来?也就是说。

  1. 能够使用方便的pdb/ipdb键盘快捷键通过您的代码进行step-by-step
  2. 在任何这样的步骤(例如,在给定的语句上),都可以访问成熟的IPython shell

IPython调试,如MATLAB中所示:

这种类型的“增强调试”的例子可以在MATLAB中找到,用户总是可以完全访问MATLAB引擎/shell,而且她仍然可以通过自己的代码进行,定义条件断点等。从我与其他用户讨论过的情况来看,这是人们在从MATLAB迁移到IPython时最缺少的调试功能。

Emacs和其他编辑器中的IPython调试:

我不想让这个问题过于具体,但我主要是在Emacs工作,所以我想知道是否有任何方法将这个功能引入其中。理想情况下,、Emacs (或编辑器)将允许程序员在代码的任何位置设置断点,并与解释器或调试器通信,使其停止在您选择的位置,并在该位置将其带到一个完整的IPython解释器中。

EN

回答 15

Stack Overflow用户

回答已采纳

发布于 2017-04-14 14:14:04

您可以使用IPython的魔术。只需在%pdb中调用IPython,当发生错误时,将自动丢弃到ipdb。虽然您没有立即采取步骤,但之后您将进入ipdb

这使得调试单个函数变得容易,因为您只需用%load加载一个文件,然后运行一个函数。您可以在正确的位置使用assert强制出错。

%pdb是一种线魔法。叫它%pdb on%pdb 1%pdb off%pdb 0。如果调用时不带任何参数,则充当切换。

票数 81
EN

Stack Overflow用户

发布于 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提示工具包的。

票数 120
EN

Stack Overflow用户

发布于 2014-04-30 12:28:48

(2016年5月28日更新)在Emacs中使用RealGUD

对于Emacs中的任何人,这条线将展示如何使用以下方法完成OP中描述的所有内容(以及更多)

  1. Emacs中的一个新的重要调试器称为RealGUD,它可以与任何调试器(包括ipdb)一起操作。
  2. Emacs包isend-mode

这两个包的组合非常强大,允许您精确地重新创建OP中描述的行为,并进行更多的操作。

关于维基文章 of RealGUD for ipdb的更多信息。

原来的答案:

在尝试了许多不同的方法来调试Python之后,包括这个线程中提到的所有内容之后,我首选的使用IPython调试Python的方法之一是使用嵌入式shell。

定义自定义嵌入式IPython外壳:

将脚本中的以下内容添加到PYTHONPATH中,以便ipsh()方法可用。

代码语言:javascript
复制
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

使用它:

代码语言:javascript
复制
def my_function(b):
  a = b
  ipsh() # <- This will embed a full-fledged IPython interpreter
  a = 4

然后,我以下列方式之一调用my_function(2)

  1. 通过运行从Unix shell调用此函数的Python程序
  2. 或者直接从IPython调用它

不管我如何调用它,解释器都会停在写着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对象的任何后续实例化。

票数 40
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16867347

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档