Python asyncio future add_done_callback然后取消未来



我有一个问题来理解异步的工作原理 如果我创建一个未来的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

**更新 设定之后是火,我把add_done_callback绑定到未来 当我取消未来和未来的状态更改为取消并完成时,我希望_future_set也会被取消。print(_future_set.cancelled())将是真的

从文档字符串(在我的 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上注册期货。前者是创建期货的首选方法。注:注:除非停止,否则代码仍将在loop.run_forever()调用时永久运行,因此仍然永远不会到达您的 print 语句。


进一步的附录:如果您实际运行问题中的代码,则会在f.exception()中引发异常,根据文档

异常()

返回在此未来设置的异常。

仅当将来完成时,才会返回异常(如果未设置异常,则返回 None)。如果将来已取消,则引发已取消错误。如果未来尚未完成,则会引发 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)

然后你会得到预期的输出。

最新更新