2014-12-12 1 views
1

У меня есть функция генератора, которая ошибочно работает, которую я хотел бы вызвать из консоли pdb, а затем пройдите через каждую ее итерацию, чтобы увидеть, какая часть этого неверна. Я надеялся, что я могКак выполнить произвольный вызов функции генератора с консоли pdb?

(Pdb) !pdb.runcall(broken_function, with_arg) 

но поскольку функция является генератором все, что я вернулся был

<generator object broken_function at 0x2badc30> 

Кто-нибудь есть какие-либо идеи о том, что я могу сделать в этой точке?

Редактировать: Я должен был сделать это ясно раньше: я бы хотел просто установить точку останова в соответствующем цикле, но я запустил код из (для меня) файловой системы только для чтения, что делает это непрактичным.

+0

Я видел ваши изменения и добавлены правку на мой ответ, что делает ответ ясно (вместо того, чтобы быть в середине примера). Вам не нужно устанавливать точку останова в соответствующем цикле. –

ответ

2

Это то, что я хотел бы попробовать:

  1. Установите точку останова в корпусе генератора.
  2. В командной строке pdb вызывается функция, которая выполняет итерацию по всем значениям генератора.

. Пример:

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() вместо того, чтобы требовать от вас, чтобы передать генератор в

+0

Проблема в том, что я запускаю код из каталога только для чтения, поэтому изменение кода, к сожалению, не является вариантом! Наверное, я должен был это указать. – kqr

+0

возможно, вы можете вызвать 'pdb.run (« for e in mygen(): pass »)' вместо определения 'testgen()'. – ErikR

+0

Возможно, вы можете вызвать 'next (the_gen)' из pdb? –

3

Edit: Короткая версия:

Варианты:

  1. Задайте свою функцию с помощью pdb.run('my_module.my_method()') и пройдите через генератор.

  2. Позвоните в 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() внутри вашего генератора, но для этого требуется изменение/размещение отладки в вашем целевом коде, что может быть не идеальным.

+0

Это не работает, когда 'yippy_dog' является функцией генератора, так как он немедленно возвращается с генератором. – kqr

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' 
+2

Не уверен, что этот ответ нужен OP, но это решило проблему для меня. Вы можете сделать это в ipython, импортировав функцию генератора, захватив генератор (например, 'g = gen()'), а затем вызывая ipdb.runcall в методе 'next' (например,' ipdb.runcall (g.next) '). – toes