ca9163d9
ca9163d9

Reputation: 29227

asyncio.gather vs list comprehension

In the following code, are get_all_details_1 and get_all_details_2 behave the same?

async def get_details(category, limit):
    async with limit:
        # ... 

limit = asyncio.Semaphore(4)
a_list = .... # a big list

async def get_all_details_1():
    b_list = await asyncio.gather(*[get_details(x, limit) for x in a_list])
    # ....


async def get_all_details_2():
    b_list = [await get_details(x, limit) for x in a_list]
    # ....

Upvotes: 5

Views: 2695

Answers (1)

orlp
orlp

Reputation: 117916

Absolutely not! Example:

import asyncio
import time

async def slowtask():
    await asyncio.sleep(1)

async def gather():
    await asyncio.gather(*[slowtask() for _ in range(10)])

async def listcomp():
    [await slowtask() for _ in range(10)]

start = time.time()
asyncio.run(gather())
print("gather", time.time() - start)

start = time.time()
asyncio.run(listcomp())
print("listcomp", time.time() - start)

gives us:

gather 1.0030405521392822
listcomp 10.015443325042725

asyncio.gather properly allows multiple async tasks to run asynchronously while the list comprehension awaits one after the other, leading to effectively serial code.

Upvotes: 7

Related Questions