【问题标题】:How to await method in loop?如何在循环中等待方法?
【发布时间】:2017-04-06 06:03:25
【问题描述】:

我有以下方法可以为我生成数据:

async def generate_url(self, video_id):
    data = await self.s3.generate_presigned_url(...video_id...)
    return data

def convert_to_json(self, urls):
    ids = [self.generate_url(url) for url in urls]
    ...

如何在convert_to_json 中正确等待generate_url

【问题讨论】:

  • 假设convert_to_json 是异步的,那么您只需等待ids 的每个元素,我认为async for data in ids: 会起作用。

标签: python asynchronous async-await python-asyncio aiohttp


【解决方案1】:

您可以在任务列表周围使用wait 包装器:

async def convert_to_json(self, urls):
    tasks = [self.generate_url(url) for url in urls]
    await asyncio.wait(tasks)

或者,如果不能将convert_to_json方法标记为async,则同步等待:

import asyncio

def convert_to_json(self, urls):
    loop = asyncio.get_event_loop()
    tasks = [self.generate_url(url) for url in urls]
    loop.run_until_complete(asyncio.wait(tasks))

您也可以尝试实现an async iterator 并将其与async for 语法一起使用,如下所示:

class Loader:
    def __init__(self, urls):
        self._urls = iter(urls)

    async def generate_url(self, video_id):
        data = await self.s3.generate_presigned_url(...video_id...)
        return data

    def __aiter__(self):
        return self

    async def __anext__(self):
        try:
            url = next(self._urls)
        except StopIteration:
            raise StopAsyncIteration
        data = await self.generate_url(url)
        return data

async for id in Loader(urls):
    print(id)

【讨论】:

    【解决方案2】:

    对我来说,它的工作原理是这样的:

    import asyncio
    
    class A:
        def __init__(self):
            pass
    
        async def generate_url(self, video_id):
            data = await self.s3.generate_presigned_url(...video_id...)
            return data
    
        def add_to_ids(self, id):
            ids.append(id.result())
    
        def convert_to_json(self, urls):
            loop = asyncio.get_event_loop()
    
            ids = []
            tasks = []
    
            for url in urls:
                task = asyncio.ensure_future(self.generate_url(url))
                task.add_done_callback(self.add_to_ids)
                tasks.append(task)
            tasks = asyncio.gather(*tasks)
    
            loop.run_until_complete(tasks)
            loop.close()
    
    a = A()
    a.convert_to_json([1, 2, 3])
    

    享受吧!

    【讨论】:

      【解决方案3】:

      如果您还没有使用循环,请尝试:

      loop = asyncio.get_event_loop()
      ids = loop.run_until_complete(asyncio.gather(*[self.generate_url(url) for url in urls]))
      

      或者在协程中:

      ids = await asyncio.gather(*[self.generate_url(url) for url in urls])
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-05-22
        • 2021-06-21
        • 1970-01-01
        • 2023-01-20
        • 2020-01-04
        • 2015-07-03
        • 1970-01-01
        相关资源
        最近更新 更多