我有一个行为不正常的生成器函数,我想从pdb控制台调用它,然后逐步完成它的每次迭代,看看它的哪个部分是错误的。我希望我能
(Pdb) !pdb.runcall(broken_function, with_arg)
但是因为函数是一个生成器所以我回来了
<generator object broken_function at 0x2badc30>
有没有人知道我现在能做些什么?
编辑:我之前应该已经说清楚了:我当然想在相关循环中设置一个断点,但是我正在运行一个(对我来说)只读文件系统的代码,使那不切实际。
答案 0 :(得分:3)
编辑:简短版本:
选项:
使用pdb.run('my_module.my_method()')
定位您的功能并逐步完成生成器。
将pdb作为脚本python -m pdb my_script.py
调用。
使用测试文件yippy_dog.py:
def yippy_dog():
for i in range(10):
print("YIP YIP!")
yippy_dog()
要从pdb控制台定位生成器,导入所需的模块,然后在调用相关方法时调用.run():
>>> import pdb
>>> import yippy_dog
YIP YIP!
~~~
YIP YIP!
YIP YIP!
>>> pdb.run('yippy_dog.yippy_dog()')
> <string>(1)<module>()
(Pdb) s
--Call--
> /private/tmp/yippy_dog.py(1)yippy_dog()
-> def yippy_dog():
(Pdb) s
> /private/tmp/yippy_dog.py(2)yippy_dog()
-> for i in range(10):
(Pdb) s
> /private/tmp/yippy_dog.py(3)yippy_dog()
-> print("YIP YIP!")
(Pdb) s
YIP YIP!
> /private/tmp/yippy_dog.py(2)yippy_dog()
-> for i in range(10):
(Pdb) s
> /private/tmp/yippy_dog.py(3)yippy_dog()
-> print("YIP YIP!")
(Pdb) s
YIP YIP!
> /private/tmp/yippy_dog.py(2)yippy_dog()
-> for i in range(10):
(Pdb) s
> /private/tmp/yippy_dog.py(3)yippy_dog()
-> print("YIP YIP!")
(Pdb) s
YIP YIP!
> /private/tmp/yippy_dog.py(2)yippy_dog()
-> for i in range(10):
(Pdb)
要从命令行运行调用pdb作为脚本的生成器,请调用pdb模块并跳到相关框架:
$ python -m pdb yippy_dog.py
> /private/tmp/yippy_dog.py(1)<module>()
-> def yippy_dog():
(Pdb) step
> /private/tmp/yippy_dog.py(5)<module>()
-> yippy_dog()
(Pdb) step
--Call--
> /private/tmp/yippy_dog.py(1)yippy_dog()
-> def yippy_dog():
(Pdb) step
> /private/tmp/yippy_dog.py(2)yippy_dog()
-> for i in range(10):
(Pdb) step
> /private/tmp/yippy_dog.py(3)yippy_dog()
-> print("YIP YIP!")
(Pdb) step
YIP YIP!
> /private/tmp/yippy_dog.py(2)yippy_dog()
-> for i in range(10):
(Pdb) step
> /private/tmp/yippy_dog.py(3)yippy_dog()
-> print("YIP YIP!")
(Pdb) step
YIP YIP!
> /private/tmp/yippy_dog.py(2)yippy_dog()
-> for i in range(10):
当然,您可以通过将set_trace()
置于生成器中来手动强制断点,但这需要修改/在目标代码中进行调试,这可能并不理想。
答案 1 :(得分:2)
这就是我想要的:
示例:
def mygen():
for e in ...:
... -- set a break point here, for instance
yield ...
def testgen(g): -- call this function from the pdb prompt
for e in g: pass
您也可以让testgen()
直接致电mygen()
,而不是要求您传递发电机。
答案 2 :(得分:2)
我试过这个。似乎工作,但也许它不是你想要的:
# gen.py
def gen():
while True:
yield "foo"
if __name__ == "__main__":
g = gen()
然后我启动pdb:
$ python2.7 -m pdb gen.py
> /home/elasand/prog/gen.py(1)<module>()
-> def gen():
(Pdb) s
> /home/elasand/prog/gen.py(5)<module>()
-> if __name__ == "__main__":
(Pdb) s
> /home/elasand/prog/gen.py(6)<module>()
-> g = gen()
(Pdb) s
--Return--
> /home/elasand/prog/gen.py(6)<module>()->None
-> g = gen()
(Pdb) !next(g)
'foo'
答案 3 :(得分:2)
您可以轻松进入任何生成器并逐步完成,我的回答与toes有些相似。
假设我们有一个功能
no = 4
def func(no):
for i in range(0,no):
yield i
要进入函数func
并迭代它,可以使用pdb.runcall
和迭代器next
,因此我使用了两者并创建了函数debug_gen
和这个函数有助于调试发生器。
def debug_gen(func,*args,**kwargs):
x = func(*args, **kwargs)
results = []
try:
while True:
result = pdb.runcall(next, x)
results.append(result)
except StopIteration:
return results
所以你只需要使用参数和关键字参数(如果有的话)将函数传递给debug_gen
,之后,你必须在任何地方调用debug_gen
函数来调试任何生成器函数。