asyncio.as_completed是否产生期货或协程?

时间:2018-11-01 19:45:03

标签: python python-3.x python-asyncio

来自 func bindToKeyboard(){ NotificationCenter.default.addObserver(self, selector: #selector(UIView.keyboardWillChange(_:)), name: UIApplication.keyboardWillChangeFrameNotification , object: nil) } docs

  

asyncio

     

在aws集中同时运行等待对象。 返回迭代器   的未来对象。返回的每个未来对象都代表最早的对象   剩余的等待结果集的结果。

我假设这些asyncio.as_completed(aws, *, loop=None, timeout=None)对象中的每一个都具有asyncio.Future中描述的方法:Future.cancelled().exception()。但似乎产生的元素只是协程,而不是.result()对象。我想念什么?

这似乎打败了Future的描述。如果我需要.as_completed(),协程如何“完成”?

await

最终,我对此很在意,是因为我想像在>>> import asyncio >>> import aiohttp >>> >>> async def get(session, url): ... async with session.request('GET', url) as resp: ... t = await resp.text() ... return t ... >>> async def bulk_as_completed(urls): ... async with aiohttp.ClientSession() as session: ... aws = [get(session, url) for url in urls] ... for future in asyncio.as_completed(aws): ... for i in ('cancelled', 'exception', 'result'): ... print(hasattr(future, i)) ... print(type(future)) ... try: ... result = await future ... except: ... pass ... else: ... print(type(result)) ... print() ... >>> >>> urls = ( ... 'https://docs.python.org/3/library/asyncio-task.html', ... 'https://docs.python.org/3/library/select.html', ... 'https://docs.python.org/3/library/this-page-will-404.html', ... ) >>> >>> asyncio.run(bulk_as_completed(urls)) False False False <class 'coroutine'> <class 'str'> False False False <class 'coroutine'> <class 'str'> False False False <class 'coroutine'> <class 'str'> 中那样使异常冒泡。考虑添加一个伪造的URL,当{ {1}}被称为:

asyncio.gather(..., return_exceptions=True)

我想 能做的是这样的事情(使用Future对象的方法,但是这些根本不是Future对象,这就是问题所在):

session.request()

1 个答案:

答案 0 :(得分:3)

  

我想做的就是这样[...]

也许不那么方便,但是您应该能够使用如下代码提取异常:

async def bulk_as_completed(urls):
    async with aiohttp.ClientSession() as session:
        aws = [get(session, url) for url in urls]
        for future in asyncio.as_completed(aws):
            try:
                res = await future
            except Exception as e:
                res = e
            # ...
            # [Do something with `res`]
  

这种[生产协程而不是期货]似乎使.as_completed()的描述无法实现。如果我需要等待,协程如何“完成”?

不是。首次实现asyncio.as_completed时,不存在异步迭代器。如果没有异步迭代,就无法在期货完成时退还期货,因此as_completed会通过(立即)产生等待结果以获得实际结果的伪等待收益来伪造期货。

即使as_completed产生了实际的期货,它也不会对您的用例有所帮助,因为如果没有人等待,这些期货就不会完成。为了提供as_completed产生预期的完成期货的语义,as_completed需要实现异步迭代,其等效__next__可以等待。

as_completed的令人惊讶的行为已经在之前提出过,我已经提交了an issue来通过提供异步迭代来修复它。一旦实施,您的原始代码将在for更改为async for的情况下起作用。