我正在尝试两种方式来停止无限循环的运行:
- supervisor_1: 通过编程方式取消任务 - supervisor_2: 使用 Ctrl+C 终止任务
虽然在中断时supervisor_2不会抛出任何错误,但我无法防止supervisor_1报错
以下是代码:
- supervisor_1: 通过编程方式取消任务 - supervisor_2: 使用 Ctrl+C 终止任务
虽然在中断时supervisor_2不会抛出任何错误,但我无法防止supervisor_1报错
Task was destroyed but it is pending!
。你有任何想法吗?以下是代码:
import asyncio
import aioredis
from functools import partial
class Listener:
def __init__(self, redis_conn):
self.redis_conn = redis_conn
async def forever(self, loop_name):
counter = 0
try:
while True:
print('{}: {}'.format(loop_name, counter))
counter += 1
await asyncio.sleep(1)
except asyncio.CancelledError:
print('Task Cancelled')
self.redis_conn.close()
await self.redis_conn.wait_closed()
async def supervisor_1(redis_conn):
redis_conn = await redis_conn
l = Listener(redis_conn)
task = asyncio.ensure_future(
asyncio.gather(l.forever('loop_1'),
l.forever('loop_2')))
await asyncio.sleep(2)
task.cancel()
async def supervisor_2(redis_conn):
redis_conn = await redis_conn
l = Listener(redis_conn)
await asyncio.gather(l.forever('loop_1'),
l.forever('loop_2'))
if __name__ == '__main__':
redis_conn = aioredis.create_pool(('localhost', 5003), db=1)
loop = asyncio.get_event_loop()
run = partial(supervisor_2, redis_conn=redis_conn)
task = asyncio.ensure_future(run())
try:
loop.run_until_complete(task)
except KeyboardInterrupt:
print('Interruped !')
task.cancel()
loop.run_forever()
finally:
loop.close()
@更新:
感谢@Gerasimov,这里是修复问题的版本,但有时在按下键盘中断时仍会引发错误:
async def supervisor(redis_conn):
redis_conn = await redis_conn
l = Listener(redis_conn)
task = asyncio.ensure_future(
asyncio.gather(l.forever('loop_1'),
l.forever('loop_2'))
)
await asyncio.sleep(10)
task.cancel()
with suppress(asyncio.CancelledError):
await task
async def kill_tasks():
pending = asyncio.Task.all_tasks()
for task in pending:
task.cancel()
with suppress(asyncio.CancelledError):
await task
并且
if __name__ == '__main__':
redis_conn = aioredis.create_pool(('localhost', 5003), db=1)
loop = asyncio.get_event_loop()
run = partial(supervisor, redis_conn=redis_conn)
task = asyncio.ensure_future(run())
try:
loop.run_until_complete(task)
except KeyboardInterrupt:
print('Interruped !')
loop.run_until_complete(kill_tasks())
finally:
loop.close()
loop.run_until_complete(kill_tasks())
移动到finally块中,在loop.close()
之前。这应该可以解决问题。我不确定你的run()
协程做了什么,但是可能会出现这种情况:当它完成时,但某些任务没有完成:在关闭事件循环时,即使没有发生KeyboardInterrupt
,也会收到警告。 - Mikhail Gerasimovsuppress()
调用将会吞噬 那个CancelledError
,实际上,await task
可能会被提前中止。看起来当前的 asyncio(至少在 3.8 版本)可能没有办法避免这种情况。 - Peter Hansen