How do I wait for a method in a loop?

I have the following method that generates data for me:

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

      

What is the correct way to wait generate_url

in convert_to_json

?

+3


source to share


3 answers


You can use a wait

wrapper around the task list:

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

      

Or, if you cannot mark the convert_to_json

method as async

, wait synchronously:



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

      

Also you can try to implement an iteratorasync

and use it with syntax async for

like this:

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)

      

+5


source


For me it worked something like this:

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

      



Enjoy!

0


source


If you are not already using a loop, try:

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

      

Or in a coroutine:

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

      

0


source







All Articles