3
鑑於此示例代碼如何在調試異步函數時檢索原始調用堆棧?
#!/usr/bin/python3
import asyncio
async def f1():
await f2()
async def f2():
try:
await asyncio.sleep(1)
except BaseException as exc:
import pdb;pdb.set_trace()
pass
async def main():
f = asyncio.ensure_future(f1())
await asyncio.sleep(0.5)
f.cancel()
await f
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
在斷點處的堆棧跟蹤看起來是這樣的:
(Pdb) w
/tmp/t.py(19)<module>()
-> loop.run_until_complete(main())
/usr/lib/python3.5/asyncio/base_events.py(325)run_until_complete()
-> self.run_forever()
/usr/lib/python3.5/asyncio/base_events.py(295)run_forever()
-> self._run_once()
/usr/lib/python3.5/asyncio/base_events.py(1254)_run_once()
-> handle._run()
/usr/lib/python3.5/asyncio/events.py(125)_run()
-> self._callback(*self._args)
/usr/lib/python3.5/asyncio/tasks.py(293)_wakeup()
-> self._step(exc)
/usr/lib/python3.5/asyncio/tasks.py(241)_step()
-> result = coro.throw(exc)
> /tmp/t.py(11)f2()
-> pass
這是不好的,因爲我再也看不到F2()最初是從F1被稱爲() 。
如何找回原來的調用堆棧,因爲Python是能夠做到這一點通過簡單的單步?:
$ python3 t.py
> /tmp/t.py(11)f2()
-> pass
(Pdb) s
--Return--
> /tmp/t.py(11)f2()->None
-> pass
(Pdb) s
--Call--
> /tmp/t.py(5)f1()
-> await f2()
(Pdb) s
--Return--
> /tmp/t.py(4)f1()->None
那麼,單步跳過f2()的結尾將返回到f1,所以信息必須隱藏起來*某處* ... –
我已經更新了我的答案。我希望我的解釋能夠闡明你的問題。 –
嗯。所以顯然這一切都是透明地由C運行時處理的,而我從來沒有注意過任何它?因爲當我單步通過我的f2()的末尾時,我立即在f1()中結束。 (我相應地更新了這個問題。) –