我有一个问题需要了解asyncio的工作原理
如果我创建了未来future = asyncio.Future()
,则添加add_done_callback(done_callback)
,之后取消未来
future.cancel()
done_callback不应该被解雇?
我尝试使用loop.run_forever()
,但我最终得到了无限循环。
我有一个小示例代码:
_future_set = asyncio.Future()
def done_callback(f):
if f.exception():
_future_set.set_exception(f.exception)
elif f.cancelled():
_future_set.cancel()
else:
_future_set.set_result(None)
async def check_stats(future):
while not future.cancelled():
print("not done")
continue
loop.stop()
def set(future):
if not _future_set.done():
future.add_done_callback(done_callback)
loop = asyncio.new_event_loop()
future = loop.create_future()
asyncio.ensure_future(check_stats(future), loop=loop)
set(future)
future.cancel()
loop.run_forever() # infinite
print(_future_set.cancelled())
我知道缺少某些东西,也许这不是行为,但我会很高兴在这里得到一点帮助。
我正在使用python 3.6
**更新
设置为fire后,我将add_done_callback绑定到将来
当我取消未来并且将来的状态更改为已取消并完成时,我希望_future_set
也将被取消。
并且print(_future_set.cancelled())
将为True
答案 0 :(得分:1)
来自docstring(在我的unix系统上)help(loop.run_forever)
:
run_forever() method of asyncio.unix_events._UnixSelectorEventLoop instance
Run until stop() is called.
当你致电loop.run_forever()
时,在ioloop实例上调用stop()
之前,程序不会超过该行,并且代码中没有任何内容可以这样做。
loop.run_forever()
基本上是这样做的:
def run_forever(self):
while not self.stopped:
self.check_for_things_to_do()
如果不了解您想要达到的目标,那么很难帮助您。但是,您似乎期望loop.run_forever()
在执行python代码时是异步的,但事实并非如此。 IOLoop将继续循环并检查filevents并在期货上触发回调,并且只有在被告知停止循环时才会返回到它所调用的点。
future = loop.create_future()
或future = asyncio.Future(loop=loop)
向ioloop注册期货。前者是创造未来的the preferred method。 N.B。代码仍然会在loop.run_forever()
调用时永远运行,除非它被停止,因此仍然无法访问您的print语句。
进一步补充:如果您实际运行了问题中的代码,则f.exception()
会引发异常,as per the docs:
<强>例外()强>
返回在此未来设置的异常。
仅在未来完成时才返回异常(如果未设置异常,则返回None)。如果未来被取消,则引发CancelledError。如果未来尚未完成,则引发InvalidStateError。
这意味着done_callback()
的调用将在第一个if f.exception()
停止。因此,如果您将done_callback()
切换为:
def done_callback(f):
if f.cancelled():
_future_set.cancel()
elif f.exception():
_future_set.set_exception(f.exception)
else:
_future_set.set_result(None)
然后你得到预期的输出。