Tasks and Futures

Creating and Managing Tasks

Tasks are created from coroutines and managed by the event loop. You can create tasks using asyncio.create_task() or loop.create_task(). Tasks allow for concurrent execution of multiple coroutines and can be awaited to get their result once they complete.

import asyncio

async def example_task():
    print("Task started")
    await asyncio.sleep(1)
    print("Task finished")

async def main():
    task = asyncio.create_task(example_task())
    await task

asyncio.run(main())

Using Futures for Result Handling

Futures represent the result of an asynchronous operation. They can be awaited to get the result once the operation completes. Futures are often used in conjunction with tasks to manage the outcome of asynchronous operations.

import asyncio

async def set_future_value(fut):
    await asyncio.sleep(2)
    fut.set_result("Future is done!")

async def main():
    loop = asyncio.get_event_loop()
    fut = loop.create_future()
    loop.create_task(set_future_value(fut))
    result = await fut
    print(result)

asyncio.run(main())

Combining Tasks and Futures

Tasks and futures can be combined to manage complex asynchronous workflows. Tasks can await futures, and futures can be set with the results of tasks. This combination allows for flexible and powerful asynchronous programming patterns.

import asyncio

async def process_data():
    await asyncio.sleep(1)
    return "Data processed"

async def main():
    future = asyncio.Future()
    task = asyncio.create_task(process_data())
    task.add_done_callback(lambda t: future.set_result(t.result()))
    result = await future
    print(result)

asyncio.run(main())