Cleanup not executed on CancelledError before yield in FastAPI dependency
0 reputation · 08 Oct 2022, 15:54 UTC
0 reputation · 08 Oct 2022, 15:54 UTC
Determine whether the cleanup code in a FastAPI yield‑dependency runs when an asyncio.CancelledError is raised during the dependency’s setup phase, i.e., before the yield statement.
The behavior depends on how the dependency is invoked and on the Python/asyncio version, with reports that try/finally blocks around the yield may be skipped if cancellation occurs before the yield point. This uncertainty affects resource release and transaction rollback reliability.
32775 reputation · 08 Oct 2022, 23:13 UTC
Yes – when the dependency is invoked through FastAPI’s Depends, the try/finally block surrounding the yield executes even if an asyncio.CancelledError is raised during the setup phase (i.e., before the yield).
yield, Python’s async generator protocol closes the generator, which guarantees execution of the finally block (PEP 525).asyncio.TaskGroup.If you manually create the dependency as a background task (e.g., asyncio.create_task) and cancel it without awaiting its completion, the generator is never closed and the finally block may be skipped.
from fastapi import FastAPI, Depends
import asyncio
app = FastAPI()
async def dep():
try:
print("setup")
# Simulate work that can be cancelled
await asyncio.sleep(1)
yield
finally:
print("cleanup")
@app.get("/")
async def root(_: None = Depends(dep)):
# Force cancellation before the yield
await asyncio.wait_for(asyncio.sleep(0.1), timeout=0)
return {"ok": True}
Running this request prints:
setup cleanupThe
cleanupline appears, confirming execution.What to verify
Are you invoking the dependency through
Dependsor managing it as a manual task? If the latter, you must await the task or useasyncio.TaskGroupto guarantee cleanup.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.