如何在循环中等待方法?

How to await method in loop?

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

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

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

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])

尽情享受吧!

您可以使用 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)

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

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])