如何自动化pdb命令?

时间:2018-06-02 19:26:19

标签: python python-3.x debugging pdb cpython

我在某个函数func上调用pdb,即

def fun():
    a = 10
    c = fun2(a)
    d = 40
    return c+d
def fun2(a):
    xyz ='str'
    return a+10

现在我正在使用pdb.runcall(func,a,b)运行pdb它将打开一个pdb控制台进行调试,现在假设我按2次s(步骤)和qquitpdb控制台中 但问题是我不想手动执行此操作,我想制作一些类似这样的脚本(自动告诉pdb前两个命令是s然后第三个是q),我问因为有许多函数需要至少两次c(继续)才能完全执行函数,以便它可以产生/返回一些有效的输出(比如说生成器)

任何帮助对我都是一个严重的帮助。

1 个答案:

答案 0 :(得分:1)

更好地理解问题后更新:

总的来说,我不认为这是测试代码的理想方式;为可测试性设计代码(例如使用TDD)通常会产生更容易测试的函数(例如使用模拟/虚假对象,依赖注入等),我鼓励您考虑重构代码(如果可能)。这种方法的另一个问题是测试可能与代码紧密耦合。但是,我会在这里假设您知道自己在做什么,并且无论出于何种原因,上述内容都不是一种选择。

脚本pdb

如果你想从代码脚本化pdb,实际上这可以通过实例化你自己的pdb.Pdb类并传入stdin,并在撰写本文时stdout参数(我不确定两者都应该被要求 - 我已经提交了https://bugs.python.org/issue33749)。

示例(我刚将额外的输入参数添加到fun):

def fun(i):
    a = 10 + i
    c = fun2(a)
    d = 40
    return c+d
def fun2(a):
    xyz ='str'
    return a+10

import pdb
import io
output = io.StringIO()
# this contains the pdb commands we want to execute:
pdb_script = io.StringIO("p i;; i = 100;; n;; p a;; c;;")
mypdb = pdb.Pdb(stdin=pdb_script, stdout=output)

正常结果(无脚本):

In [40]: pdb.runcall(fun, 1)
    ...:
> <ipython-input-1-28966c4f6e38>(2)fun()
-> a = 10 + i
(Pdb)
(Pdb) c
Out[40]: 61

脚本化的pdb:

In [44]: mypdb = pdb.Pdb(stdin=pdb_script, stdout=output)

In [45]: mypdb.runcall(fun, 1)
Out[45]: 160

In [50]: print(output.getvalue())
> <ipython-input-1-28966c4f6e38>(2)fun()
-> a = 10 + i
(Pdb) 1
> <ipython-input-1-28966c4f6e38>(3)fun()
-> c = fun2(a)
110

您可能会发现使用pdb_script.seek(0)有助于重置脚本。

原始答案 - 使用条件断点

听起来你真正想要的只是在你的代码处于特定状态时进入调试器。这可以通过条件断点来完成(有关详细信息,请参阅pdb docs)。 例如,假设您想要fun2 a > 10

   ...:

In [2]: import pdb

In [3]: pdb.runcall(fun, 1)
> <ipython-input-1-28966c4f6e38>(2)fun()
-> a = 10 + i
(Pdb) break fun2, a > 10
Breakpoint 1 at <ipython-input-1-28966c4f6e38>:6
(Pdb) c
> <ipython-input-1-28966c4f6e38>(7)fun2()
-> xyz ='str'
(Pdb) c
Out[3]: 61

In [4]: pdb.runcall(fun, -1)
> <ipython-input-1-28966c4f6e38>(2)fun()
-> a = 10 + i
(Pdb) c
Out[4]: 59

请注意,在第一种情况下,您点击了断点,而第二种情况则没有。

原始答案 - 使用断点并在命中时执行命令

您也可以尝试设置断点并使用commands工具。