鉴于此示例代码
#!/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
答案 0 :(得分:3)
没办法,抱歉。
这是不可能的,至少在Python 3.5
中<强> UPD 强>
内部python框架引用外部框架(fr.f_back
),可以显示堆栈跟踪。
但它没有引用等待内部协议的外部协程。
您的代码演示了一个非常有趣的案例。
更简单的例子:
#!/usr/bin/python3
import asyncio
import sys
import traceback
async def f1():
await f2()
async def f2():
import pdb;pdb.set_trace()
loop = asyncio.get_event_loop()
loop.run_until_complete(f1())
我们将在跟踪上看到你的协同程序:
(Pdb) w
/tmp/3.py(12)<module>()
-> loop.run_until_complete(f1())
/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(239)_step()
-> result = coro.send(None)
/tmp/3.py(7)f1()
-> await f2()
> /tmp/3.py(9)f2()->None
-> import pdb;pdb.set_trace()
但在您的情况下情况有所不同:f2()
等待sleep()
。
它在内部以下列方式工作:sleep()
返回 future对象,f2()
将(不返回)它返回f1()
,再次产生未来。在这种情况下,最顶层的调用者是f
main
通过ensure_future()
调用创建的任务 sleep()
。
当您取消任务时,它会取消大多数内部服务员(将来由f1 -> f2 -> sleep
返回),而不会自上而下地通过sleep
链,但明确取消$("#appended").load("test_inner.svg svg > *");
并在链中弹出自下而上的订单。
为什么你只看到堆栈上的最后一个协程 - 在异常展开时会出现所有其他协程。