我的龙卷风处理程序中具有以下方法:
async def get(self):
url = 'url here'
try:
async for batch in downloader.fetch(url):
self.write(batch)
await self.flush()
except Exception as e:
logger.warning(e)
这是downloader.fetch()的代码:
async def fetch(url, **kwargs):
timeout = kwargs.get('timeout', aiohttp.ClientTimeout(total=12))
response_validator = kwargs.get('response_validator', json_response_validator)
extractor = kwargs.get('extractor', json_extractor)
try:
async with aiohttp.ClientSession(timeout=timeout) as session:
async with session.get(url) as resp:
response_validator(resp)
async for batch in extractor(resp):
yield batch
except aiohttp.client_exceptions.ClientConnectorError:
logger.warning("bad request")
raise
except asyncio.TimeoutError:
logger.warning("server timeout")
raise
我想从多个并行下载器中下载“批处理”对象。 我希望从第一个下载器获得第一个可用批次,以此类推,直到所有下载器完成。像这样的东西(这不是工作代码):
async for batch in [downloader.fetch(url1), downloader.fetch(url2)]:
....
这可能吗?如何修改自己的操作以便能够并行地从多个协程中获得收益?
答案 0 :(得分:0)
我如何修改自己的操作以便能够并行地从多个协程中获得收益?
您需要一个函数,将两个异步序列合并为一个,并同时进行迭代,并在一个可用的情况下从另一个中产生元素。尽管当前的标准库中未包含此类功能,但您可以在find one中aiostream package。
您还可以编写自己的merge
函数,如this answer所示:
async def merge(*iterables):
iter_next = {it.__aiter__(): None for it in iterables}
while iter_next:
for it, it_next in iter_next.items():
if it_next is None:
fut = asyncio.ensure_future(it.__anext__())
fut._orig_iter = it
iter_next[it] = fut
done, _ = await asyncio.wait(iter_next.values(),
return_when=asyncio.FIRST_COMPLETED)
for fut in done:
iter_next[fut._orig_iter] = None
try:
ret = fut.result()
except StopAsyncIteration:
del iter_next[fut._orig_iter]
continue
yield ret
使用该函数,循环如下所示:
async for batch in merge(downloader.fetch(url1), downloader.fetch(url2)):
....
答案 1 :(得分:-1)