Reputation: 131
I recently started looking into asynchronous programming in Python. Let's say we want to run a function asynchronously, an example below:
async def print_i_async(no):
print("Async: Preparing print of " + str(no))
await asyncio.sleep(1)
print(str(no))
async def main_async(no):
await asyncio.gather(*(print_i_async(i) for i in range(no)))
asyncio.run(main_async(no))
This will as expected work asynchronously. It's not clear to me, however, why would we use asynchronous functions if not with asyncio.gather()
. For example:
def print_i_serial(no):
print("Serial: Preparing print of " + str(no))
time.sleep(1)
print(str(no))
for i in range(5):
print_i_serial(i)
for i in range(5):
asyncio.run(print_i_async(i))
These two functions produce the same result. Am I missing something? Is there any reason we would use an async def
if we don't use asyncio.gather()
, given this is how we actually get asynchronous results?
Upvotes: 2
Views: 2476
Reputation: 1525
There are many reasons to use asyncio
besides gather
.
What you are really asking is: are there more ways to create concurrent executions besides gather
?
To that the answer is yes.
Yes, gather
is one of the simplest and most straightforward examples for creating concurrency with asyncio
, but it's not limited to gather
.
What gather
does is creating a bunch of awaitables (if needed, for example coroutines are wrapped in a task) to wait for and return the result once all the futures are ready (and a bunch of other stuff such as propagating cancellation).
Let's examine just two more examples of ways to achieve concurrency:
as_completed
- similarly to gather
, you send in a bunch of awaitables, but instead of waiting for all of them to be ready, this method returns you the futures as they become ready, unordered.event_loop.create_task()
. This will allow you to create a task that will run on the event loop, which you can later await
. In the meantime (until you await
the task) you can continue running other code, and basically achieve concurrency (note the task will not run straightaway, but only when you yield control back to the event loop, and it handles the task).There are many more ways to achieve concurrency. You can start with these examples (the 2nd one is actually a general way you can use to create lots of different concurrent "topologies" of executions).
You can start by reading https://docs.python.org/3/library/asyncio-task.html
Upvotes: 7