How to automate pdb commands?

2019-03-05 16:48发布

I am calling pdb on some function func i.e.,

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

Now I am running pdb using pdb.runcall(func,a,b) now It will open a pdb console for debugging, now suppose I press 2 time s(step) and q to quit in pdb console but problem is I don't want to do this manually, I want to make some script which do something like this (automatic tell pdb first two command is s then third is q) , I am asking because there are many functions which needs atleast two time c (continue) to overall excecution of function so that it can yield/return some valid output (like say generators)

Any help will be a serious help for me.

1条回答
ゆ 、 Hurt°
2楼-- · 2019-03-05 17:06

Update after better understanding the question:

In general, I don't think this is the ideal way to test code; designing code for testability (e.g. using TDD) will often result in functions that are easier to test (e.g. using mocks/fake objects, dependency injection etc), and I would encourage you to consider refactoring the code if possible. The other issue with this approach is that the tests may become very tightly coupled to the code. However, I'll assume here that you know what you are doing, and that the above is not an option for whatever reason.

Scripting pdb

If you want to script pdb from code, this is actually possible by instantiating your own pdb.Pdb class and passing in the stdin and, at the time of writing, stdout argument (I'm not sure both should be required - I've filed https://bugs.python.org/issue33749).

Example (I just added the extra input argument to 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)

Normal result (no scripting):

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

Scripted 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

You may find using pdb_script.seek(0) helpful to reset the script.

Original answer - using conditional breakpoints

It sounds like what you really want is to only get into the debugger when your code is in a certain state. This can be done with conditional breakpoints (see pdb docs for details). For example, let's say you want to break in fun2 if 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

Notice in the first case you hit the breakpoint, in the second you didn't.

Original answer - using breakpoints and executing commands when hit

You could also try setting a breakpoint and using the commands facility.

查看更多
登录 后发表回答