An eager task factory starts a coroutine during task creation, changing when its side effects occur.
Python eager asyncio tasks: a coroutine can finish before create_task returns
Operation contract
A coroutine that never awaits is first created under the default task factory and is not yet done. The program awaits it, installs the eager factory, and creates the same coroutine again. The eager task is already complete when create_task returns; the prior factory is restored before shutdown.
Failure boundary
This feature requires Python 3.12 or later and was executed on the local CPython build. A coroutine that suspends still needs event-loop scheduling. Switching a whole application's task factory changes ordering and can expose assumptions about side effects, callbacks, and error observation.
Working program
import asyncio
async def cached_receipt_score():
return 47
async def inspect_creation():
loop = asyncio.get_running_loop()
ordinary = asyncio.create_task(cached_receipt_score())
print("ordinary_done_at_creation", ordinary.done())
print("ordinary_result", await ordinary)
prior_factory = loop.get_task_factory()
loop.set_task_factory(asyncio.eager_task_factory)
try:
eager = asyncio.create_task(cached_receipt_score())
print("eager_done_at_creation", eager.done())
print("eager_result", await eager)
finally:
loop.set_task_factory(prior_factory)
asyncio.run(inspect_creation())Output
ordinary_done_at_creation False
ordinary_result 47
eager_done_at_creation True
eager_result 47Costs and limits
An immediate result can avoid a scheduling step. The tradeoff is changed execution order; measure a real workload and review call sites before enabling the factory broadly.
Common Mistakes
- Do not assume every created task is scheduled for a later loop turn.
- Do not infer that a suspending coroutine completes eagerly.
- Restore a temporary task factory in a reusable event loop.
