因此,至少在有限的情况下,而且不是以我一定推荐的方式,这里的答案是肯定的。我不能保证下面的内容会在我所做的范围之外工作,但它可能会给你足够的洞察力来自己尝试。需要谨慎,因为它涉及更改未记录的属性ipython
运行时的 shell 类。 TLDR:我找到了如何ipython
调用调试器时%pdb
魔法开启或当您致电%debug
魔法,我更新了它以使用我想要的调试器。如果您只想使用对我有用的方法并且不关心搜索,请跳过接下来的两段。
长版:当你跑步时ipython
它启动一个实例TerminalInteractiveShell https://github.com/ipython/ipython/blob/master/IPython/terminal/interactiveshell.py,其中有一个debugger_cls
属性告诉你调试器ipython
将启动。不幸的是,在这个水平上TerminalInteractiveShell
, debugger_cls
实际上是类的一个属性,并且没有允许您修改它的设置器。相反,它要么被设置为Pdb
(实际上是一个更有特色的ipython
Pdb
比传统的pdb
) or TerminalPdb
(甚至更多功能)。
然而,如果你深入挖掘,你会发现debugger_cls
被传递到InteractiveShell https://github.com/ipython/ipython/blob/master/IPython/core/interactiveshell.py#L1089初始化回溯的处理方式。在那里它似乎消失在初始化中InteractiveShell
's InteractiveTB
财产,但实际上最终只是作为debugger_cls
的属性(InteractiveTB
)类(通过设置继承属性TBTools https://github.com/ipython/ipython/blob/master/IPython/core/ultratb.py#L204)。最后,这个debugger_cls
属性仅用于设置pdb
属性(或多或少通过做TBToolsInstance.pdb = TBToolsInstance.debugger_cls()
)在几个地方之一。无论如何,事实证明these属性can被改变!如果你正确地改变它们,它们就会渗透到外壳本身!重要的是,这取决于以下事实:ipython
利用特质 https://traitlets.readthedocs.io/en/stable/config.html包来创建一个Singleton
shell 的对象,这允许您从终端本身访问该对象。下面详细介绍一下。
下面我展示了您可以在以下位置运行的代码ipython
shell 来达到你想要的结果。作为一个例子,我正在替换默认的调试器(TerminalPdb
)使用我创建的修改版本可以更好地处理某些列表理解(LcTerminalPdb https://github.com/emiliosalazar/LcTerminalPdb)。该过程(您可以在ipython
shell)如下。
# import the TerminalInteractiveShell class
from IPython.terminal.interactiveshell import TerminalInteractiveShell
# grab the specific instance of the already initialized ipython
shl = TerminalInteractiveShell().instance()
# grab the InteractiveTB attribute (which is a class)
tbClass = shl.InteractiveTB
# load the debugger class you want to use; I assume it's accessible on your path
from LcTerminalPdb import LcTerminalPdb
# change tbClass's debugger_cls to the debugger you want (for consistency
# with the next line)
tbClass.debugger_cls = LcTerminalPdb
# more importantly, set the pdb attribute to an instance of the class
tbClass.pdb = tbClass.debugger_cls()
# The above line is necessary if you already have the terminal running
# (and have entered pdb at least once); otherwise, ipython will run it on
# its own
就是这样!请注意,因为您调用instance()
的方法TerminalInteractiveShell
,您正在获取当前正在运行的 shell 的对象,这就是为什么修改将影响 shell 本身以及所有后续调试。作为奖励,您可以将这些代码行添加到您的ipython_config.py https://ipython.org/ipython-doc/3/config/intro.html文件,所以你想要的调试器(LcTerminalPdb
这里)总是装载着ipython
:
c.InteractiveShellApp.exec_lines = [
'%pdb on',
'from LcTerminalPdb import LcTerminalPdb',
'from IPython.terminal.interactiveshell import TerminalInteractiveShell',
'shl = TerminalInteractiveShell().instance().InteractiveTB',
'shl.debugger_cls = LcTerminalPdb',
]
注意上面我不需要写额外的shl.pdb = shl.debugger_cls()
线,如ipython
将在第一次进入调试点时处理它。但可以肯定的是,请随意。
NOTES:
- 我只使用过测试过
LcTerminalPdb
,而且只是简短的,但它似乎工作正常
- 我怀疑只要其他
pdb
调试器具有相同的 APIpdb
(即如果它们可以被PYTHONBREAKPOINT https://peps.python.org/pep-0553/环境变量)然后它应该可以工作
- 我真的不清楚改变如此深层的属性是否会产生意想不到的效果,所以不确定我在多大程度上推荐这种方法