Is pdb suitable for debugging asyncio module?

jfong at ms4.hinet.net jfong at ms4.hinet.net
Wed Apr 4 23:02:46 EDT 2018


I have a module below and run it under pdb, the result seems not easy to xplain.
(Note: the sleep periods are in reverse order)
---------------
# asyncio_as_completed.py

import asyncio

@asyncio.coroutine
def phase(i):
    print('in phase {}'.format(i))
    yield from asyncio.sleep(0.5 - (0.1 * i))
    print('done with phase {}'.format(i))
    return 'phase {} result'.format(i)

@asyncio.coroutine
def main(num_phases):
    print('starting main')
    phases = [
        phase(i)
        for i in range(num_phases)
    ]
    print('waiting for phases to complete')
    results = []
    for next_to_complete in asyncio.as_completed(phases):
        answer = yield from next_to_complete  # <--set breakpoint here
        print('received answer {!r}'.format(answer))
        results.append(answer)
    print('results: {!r}'.format(results))
    return results

event_loop = asyncio.get_event_loop()
try:
    event_loop.run_until_complete(main(3))
finally:
    event_loop.close()
---------------

D:\Works\Python>py -m pdb asyncio_as_completed.py
> d:\works\python\asyncio_as_completed.py(3)<module>()
-> import asyncio
(Pdb) n
> d:\works\python\asyncio_as_completed.py(5)<module>()
-> @asyncio.coroutine
(Pdb) b 22
Breakpoint 1 at d:\works\python\asyncio_as_completed.py:22
(Pdb) c
starting main
waiting for phases to complete
> d:\works\python\asyncio_as_completed.py(22)main()
-> answer = yield from next_to_complete

(Pdb) n
in phase 1
in phase 0
in phase 2
Internal StopIteration    # <---
> d:\works\python\asyncio_as_completed.py(8)phase()
-> yield from asyncio.sleep(0.5 - (0.1 * i))
(Pdb) n
> d:\works\python\asyncio_as_completed.py(9)phase()
-> print('done with phase {}'.format(i))
(Pdb) n
done with phase 2
> d:\works\python\asyncio_as_completed.py(10)phase()
-> return 'phase {} result'.format(i)

(Pdb) n
Internal StopIteration: phase 2 result
> d:\works\python\asyncio_as_completed.py(22)main()
-> answer = yield from next_to_complete
(Pdb) n
> d:\works\python\asyncio_as_completed.py(23)main()
-> print('received answer {!r}'.format(answer))
(Pdb) n
received answer 'phase 2 result'    # <---
> d:\works\python\asyncio_as_completed.py(24)main()
-> results.append(answer)
(Pdb) n
> d:\works\python\asyncio_as_completed.py(21)main()
-> for next_to_complete in asyncio.as_completed(phases):
(Pdb) n
> d:\works\python\asyncio_as_completed.py(22)main()
-> answer = yield from next_to_complete

(Pdb) n
Internal StopIteration    # <---
> d:\works\python\asyncio_as_completed.py(8)phase()
-> yield from asyncio.sleep(0.5 - (0.1 * i))
(Pdb) n
> d:\works\python\asyncio_as_completed.py(9)phase()
-> print('done with phase {}'.format(i))
(Pdb) n
done with phase 1
> d:\works\python\asyncio_as_completed.py(10)phase()
-> return 'phase {} result'.format(i)

(Pdb) n
Internal StopIteration    # <---
> d:\works\python\asyncio_as_completed.py(8)phase()
-> yield from asyncio.sleep(0.5 - (0.1 * i))
(Pdb) n
> d:\works\python\asyncio_as_completed.py(9)phase()
-> print('done with phase {}'.format(i))
(Pdb) n
done with phase 0
> d:\works\python\asyncio_as_completed.py(10)phase()
-> return 'phase {} result'.format(i)

(Pdb) n
Internal StopIteration: phase 1 result    # <---
> d:\works\python\asyncio_as_completed.py(22)main()
-> answer = yield from next_to_complete
(Pdb) n
> d:\works\python\asyncio_as_completed.py(23)main()
-> print('received answer {!r}'.format(answer))
(Pdb) n
received answer 'phase 1 result'
> d:\works\python\asyncio_as_completed.py(24)main()
-> results.append(answer)
(Pdb) n
> d:\works\python\asyncio_as_completed.py(21)main()
-> for next_to_complete in asyncio.as_completed(phases):
(Pdb) n
> d:\works\python\asyncio_as_completed.py(22)main()
-> answer = yield from next_to_complete

(Pdb) n
> d:\works\python\asyncio_as_completed.py(23)main()
-> print('received answer {!r}'.format(answer))
(Pdb) n
received answer 'phase 0 result'
> d:\works\python\asyncio_as_completed.py(24)main()
-> results.append(answer)
(Pdb) n
> d:\works\python\asyncio_as_completed.py(21)main()
-> for next_to_complete in asyncio.as_completed(phases):

(Pdb) n
> d:\works\python\asyncio_as_completed.py(25)main()
-> print('results: {!r}'.format(results))
(Pdb) n
results: ['phase 2 result', 'phase 1 result', 'phase 0 result']
> d:\works\python\asyncio_as_completed.py(26)main()
-> return results
(Pdb) n
The program finished and will be restarted
> d:\works\python\asyncio_as_completed.py(3)<module>()
-> import asyncio
(Pdb)


I saw three "Internal StopIteration" lines which match the three "phase" tasks, it's OK. But there are only two "Internal StopIteration: phase x result" lines, the "phase 0" was missed. Why is that?

Best Regards,
Jach Fong


More information about the Python-list mailing list