下面是一个简单的asyncio循环,它运行两个后台任务。
他们都执行简单的计数。第一个永远计数,包裹在一个 尝试/除外。第二个计数最多为5,然后取消第一个和 停止循环。
有两种方法可以确保取消完成 -
asyncio.wait([a sequence of futures])
asyncio.wait_for(a single future)
两者都采取可选的超时。
如果我在没有超时的情况下使用第一种方法,则取消完成并且 循环停止。
如果我在没有超时的情况下使用第二种方法,则取消将来,但是 程序挂起。
如果我向第二个添加超时,它的行为与第一个相同。
这是否有原因?
我使用的是版本3.6.0。
import asyncio
from itertools import count
async def counter1():
cnt = count(1)
try:
while True:
print('From 1:', next(cnt))
await asyncio.sleep(1)
except asyncio.CancelledError:
print('counter1 cancelled')
async def counter2():
cnt = count(1)
for i in range(5):
print('From 2:', next(cnt))
await asyncio.sleep(1)
cnt1.cancel()
# await asyncio.wait([cnt1]) # works
# await asyncio.wait_for(cnt1) # hangs
await asyncio.wait_for(cnt1, 1) # works
loop.stop()
loop = asyncio.get_event_loop()
cnt1 = asyncio.ensure_future(counter1())
cnt2 = asyncio.ensure_future(counter2())
loop.run_forever()
答案 0 :(得分:1)
我在comp.lang.python上收到了以下答案 -
“当循环退出时,未处理的异常显示为警告。在此之前无法显示它,因为可能还有其他任务,即使尚未安排的任务,也可能尝试获取counter2任务的结果并处理异常。“
我在Windows上测试。我从来没有让Ctrl-C在Windows上运行,因此我使用Ctrl-Pause,它会在没有显示任何挂起的回溯的情况下崩溃解释器。
在Linux上运行程序并按Ctrl-C会显示回溯。如果我首先在Linux上进行测试,则无需发布原始问题。