从代码中进入ipython是可能的吗?

84

对于我的调试需求,pdb是相当不错的。但是,如果我能进入ipython,那就会更酷(而且有帮助)。这种事情可能吗?

13个回答

117

有一个名为 ipdb 的项目将 iPython 嵌入标准的 pdb 中,这样你就可以直接执行以下命令:

import ipdb; ipdb.set_trace()

可以使用通常的 pip install ipdb 命令进行安装。

ipdb 相对比较简短,所以您也可以在 Python 路径中的某个位置创建一个名为 ipdb.py 的文件,并将以下内容粘贴到文件中,而不是使用 easy_install:

import sys
from IPython.Debugger import Pdb
from IPython.Shell import IPShell
from IPython import ipapi

shell = IPShell(argv=[''])

def set_trace():
    ip = ipapi.get()
    def_colors = ip.options.colors
    Pdb(def_colors).set_trace(sys._getframe().f_back)

在Django中表现得非常出色。唯一的问题是我看不到我正在输入的文本,但这可能很容易修复(因为ipdb只有六行)。 - Xiong Chiamiov
4
实际上,问题在于Django为runserver分叉了一个单独的线程,每次您进行代码编辑时,它都会重新启动该线程。这通常是正常工作的,但如果您在线程被终止时处于pdb中,则终端会变得混乱。您可以通过退出runserver,运行'stty sane',然后再次启动runserver来解决此问题。 - Jeremy Dunck
1
@daniel-roseman 你好,我遇到了 ModuleNotFoundError: No module named 'IPython.Debugger'ModuleNotFoundError: No module named 'IPython.Shell'ImportError: cannot import name 'ipapi' 的问题。 - SebMa
1
@memoselyk 你好,我遇到了 ModuleNotFoundError: No module named 'IPython.Debugger'ModuleNotFoundError: No module named 'IPython.Shell'ImportError: cannot import name 'ipapi' 的问题。 - SebMa
有一种方法可以让breakpoint()函数进入ipdb。 - gerrit
@gerrit 使用环境变量 PYTHONBREAKPOINT - Harry Moreno

59
在IPython 0.11中,你可以像这样直接将IPython嵌入到你的代码中:
你的程序可能看起来像这样:
In [5]: cat > tmpf.py
a = 1

from IPython import embed
embed() # drop into an IPython session.
        # Any variables you define or modify here
        # will not affect program execution

c = 2

^D

这是运行它时发生的情况(我随意选择在现有的ipython会话中运行它。根据我的经验,像这样嵌套ipython会话可能会导致它崩溃)。

In [6]:

In [6]: run tmpf.py
Python 2.7.2 (default, Aug 25 2011, 00:06:33)
Type "copyright", "credits" or "license" for more information.

IPython 0.11 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: who
a       embed

In [2]: a
Out[2]: 1

In [3]:
Do you really want to exit ([y]/n)? y


In [7]: who
a       c       embed

1
我愚蠢地把这个放在一个(几乎无限的)循环里面。我怎么才能出来? - gerrit
3
如果您仍然在那里,请按Ctrl + d。 - confused00
2
@confused00 那将会是非常漫长的6个月后;-) - gerrit
这种方法相比于pdbipdb的优势在于,由您运行的代码引起的任何异常都会得到完整的回溯(因为您还没有“进入”其中)。对我来说,这非常有用,因为我有一种倾向,即使用pdb作为设置交互式shell的一堆变量的方式。 - Xiong Chiamiov
1
如果你被嵌套循环卡住了:def f() : pass ; IPython.embed = f,这样embed()调用就是一个无操作,然后按Ctrl + D。 - MatrixManAtYrService
显示剩余2条评论

12

如果你正在使用更新版本的IPython(> 0.10.2),你可以使用以下方法:

from IPython.core.debugger import Pdb
Pdb().set_trace()

不过最好还是使用ipdb


11

相当于

import pdb; pdb.set_trace()

使用IPython的方式大致如下:

from IPython.ipapi import make_session; make_session()
from IPython.Debugger import Pdb; Pdb().set_trace()

如果你没有安装ipdb,下面的代码会有点冗长,但这是值得了解的。调用make_session函数一次来设置颜色方案等等,然后在需要打断点的任何地方都可以调用set_trace函数。


8

我喜欢在需要设置断点的脚本中简单地粘贴这个一行代码:

__import__('IPython').Debugger.Pdb(color_scheme='Linux').set_trace()

新版本可能会使用以下内容:

__import__('IPython').core.debugger.Pdb(color_scheme='Linux').set_trace()

8
通常情况下,在使用ipython时,我会在其中使用“pdb”命令打开自动调试功能。
然后,在我的脚本所在的目录中使用“run myscript.py”命令运行脚本。
如果出现异常,ipython将在调试器内停止程序。请查看魔术ipython命令的帮助命令(%magic)。

所以没有办法写出类似于ipython.set_trace()这样的东西吗? :) - Geo

6

看起来模块最近有些变动。在IPython 0.13.1上,以下代码对我有效:

from IPython.core.debugger import Tracer; breakpoint = Tracer()

breakpoint() # <= wherever you want to set the breakpoint

虽然遗憾的是,在qtconsole中这一切都相当无用


5
较新版本的IPython提供了一种将IPython会话嵌入到任何Python程序中的简单机制。您可以按照以下步骤来嵌入IPython会话:
try:
    get_ipython
except NameError:
    banner=exit_msg=''
else:
    banner = '*** Nested interpreter ***'
    exit_msg = '*** Back in main IPython ***'

# First import the embed function
from IPython.frontend.terminal.embed import InteractiveShellEmbed
# Now create the IPython shell instance. Put ipshell() anywhere in your code
# where you want it to open.
ipshell = InteractiveShellEmbed(banner1=banner, exit_msg=exit_msg)

然后在需要进入IPython shell的时候使用ipshell()。这将允许您在代码中嵌入(甚至嵌套)IPython解释器。


3

来自IPython文档

import IPython.ipapi
namespace = dict(
    kissa = 15,
    koira = 16)
IPython.ipapi.launch_new_instance(namespace)

将以编程方式启动IPython shell。显然,namespace字典中的值只是虚拟值 - 在实践中使用locals()可能更有意义。

请注意,您必须在代码中硬编码它;它不会像pdb那样工作。如果这就是您想要的,DoxaLogos的答案可能更符合您的要求。


3

快速简单的方法:

from IPython.Debugger import Tracer
debug = Tracer()

那么就写下去吧。
debug()

无论您想从哪里开始调试程序。


1
在 Python 3.4 / IPython 3 上出现了“ImportError: No module named 'IPython.Debugger'”错误。 - ostrokach

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接