Concurrent task execution lets your app do many things at the same time. This helps your app stay fast and responsive.
Concurrent task execution in FastAPI
import asyncio from fastapi import FastAPI app = FastAPI() @app.get("/tasks") async def run_tasks(): task1 = asyncio.create_task(some_async_function1()) task2 = asyncio.create_task(some_async_function2()) results = await asyncio.gather(task1, task2) return {"results": results}
Use async def for functions that run asynchronously.
asyncio.create_task() starts tasks concurrently.
import asyncio async def task1(): await asyncio.sleep(1) return "Task 1 done" async def task2(): await asyncio.sleep(2) return "Task 2 done"
import asyncio async def main(): t1 = asyncio.create_task(task1()) t2 = asyncio.create_task(task2()) results = await asyncio.gather(t1, t2) print(results)
from fastapi import FastAPI app = FastAPI() @app.get("/run") async def run(): t1 = asyncio.create_task(task1()) t2 = asyncio.create_task(task2()) results = await asyncio.gather(t1, t2) return {"results": results}
This FastAPI app has an endpoint /tasks that runs two tasks at the same time. Task 1 waits 1 second, Task 2 waits 2 seconds. The endpoint waits for both to finish and returns their messages together.
import asyncio from fastapi import FastAPI app = FastAPI() async def task1(): await asyncio.sleep(1) return "Task 1 done" async def task2(): await asyncio.sleep(2) return "Task 2 done" @app.get("/tasks") async def run_tasks(): t1 = asyncio.create_task(task1()) t2 = asyncio.create_task(task2()) results = await asyncio.gather(t1, t2) return {"results": results}
Use asyncio.gather() to wait for many tasks at once.
Concurrent tasks help your app handle slow operations without freezing.
Remember to use async and await keywords properly.
Concurrent task execution lets your app do many things at once.
Use asyncio.create_task() and asyncio.gather() to run and wait for tasks.
FastAPI supports async endpoints to handle concurrent tasks easily.
Practice
asyncio.create_task() in FastAPI?Solution
Step 1: Understand
This function schedules a coroutine to run concurrently as a separate task without blocking the main program.asyncio.create_task()purposeStep 2: Identify the benefit in FastAPI context
Using it lets FastAPI handle multiple operations at once, improving responsiveness and efficiency.Final Answer:
It allows running multiple tasks at the same time without waiting for each to finish. -> Option DQuick Check:
Concurrent task execution = run tasks simultaneously [OK]
- Thinking create_task slows code down
- Confusing async with sync code
- Believing tasks stop until restarted
Solution
Step 1: Understand how to run and wait for multiple async tasks
asyncio.gather()runs multiple coroutines concurrently and waits for all to complete.Step 2: Check each option's correctness
await asyncio.gather(func1(), func2()) correctly usesawait asyncio.gather(func1(), func2()). await asyncio.create_task(func1()); await asyncio.create_task(func2()) starts tasks but awaits them separately, not concurrently. func1(); func2() runs functions synchronously. asyncio.run(func1(), func2()) is invalid syntax.Final Answer:
await asyncio.gather(func1(), func2()) -> Option CQuick Check:
Use gather to run and wait multiple tasks [OK]
- Awaiting tasks separately losing concurrency
- Calling async functions without await
- Using asyncio.run inside async code
import asyncio
from fastapi import FastAPI
app = FastAPI()
async def task1():
await asyncio.sleep(1)
return "Task 1 done"
async def task2():
await asyncio.sleep(2)
return "Task 2 done"
@app.get("/run")
async def run_tasks():
results = await asyncio.gather(task1(), task2())
return {"results": results}Solution
Step 1: Analyze the async tasks and their sleep durations
task1 sleeps 1 second, task2 sleeps 2 seconds. Both run concurrently with gather.Step 2: Understand gather result order
asyncio.gather returns results in the order of the input tasks, regardless of completion time.Final Answer:
{"results": ["Task 1 done", "Task 2 done"]} -> Option AQuick Check:
Gather preserves input order in results [OK]
- Assuming results order matches finish order
- Expecting partial results if one task is slower
- Confusing gather with wait
import asyncio
from fastapi import FastAPI
app = FastAPI()
async def task():
await asyncio.sleep(1)
return "Done"
@app.get("/test")
async def test():
task1 = asyncio.create_task(task())
task2 = asyncio.create_task(task())
return {"result": task1.result() + task2.result()}Solution
Step 1: Identify how task results are accessed
Callingtask1.result()immediately after creating the task tries to get the result before the task finishes, causing an error.Step 2: Understand correct way to wait for task completion
You must await the task or useawait asyncio.gather(task1, task2)before accessing results.Final Answer:
Calling task1.result() before task completion causes an error. -> Option AQuick Check:
Access task result only after await [OK]
- Accessing .result() too early
- Thinking create_task is forbidden
- Making endpoint synchronous
Solution
Step 1: Understand error handling in concurrent tasks
Usingasyncio.gather()withreturn_exceptions=Truelets all tasks run concurrently and collects exceptions as results without stopping others.Step 2: Compare options for correct concurrency and error handling
Useasyncio.gather(task1(), task2(), task3(), return_exceptions=True)and process results for exceptions. correctly runs all tasks concurrently and handles errors individually. Useawait task1(); await task2(); await task3()sequentially and catch exceptions globally. runs tasks sequentially, losing concurrency. Useasyncio.create_task()for each task but do not await them before returning. does not await tasks, so results are unavailable. Run tasks synchronously in a loop and catch exceptions inside each. runs synchronously, blocking concurrency.Final Answer:
Use asyncio.gather(task1(), task2(), task3(), return_exceptions=True) and process results for exceptions. -> Option BQuick Check:
Gather with return_exceptions handles errors concurrently [OK]
- Awaiting tasks sequentially losing concurrency
- Not awaiting tasks before returning
- Ignoring exceptions stopping all tasks
Ready to prove it?
Pass the test and this pattern moves unknown
