fastapi的backgroundtasks仅支持同步函数,不支持await协程、无异常捕获、无重试、状态不共享;需用asyncio.run()或to_thread()包装协程,关键任务应选用celery等专业队列。

FastAPI 的 BackgroundTasks 不是异步任务调度器,它只是请求结束后在同进程内开线程执行普通函数 —— 所以别指望它能 await 协程、持久化或重试。
BackgroundTasks.add_task() 只接受同步函数
你写一个 async def 函数,然后传给 add_task(),会直接报错:RuntimeError: asyncio.run() cannot be called from a running event loop。因为 BackgroundTasks 底层用的是 concurrent.futures.ThreadPoolExecutor,它只跑同步代码。
- ✅ 正确做法:把协程包装成同步调用,例如用
asyncio.run()(仅限单次、无事件循环嵌套场景) - ✅ 更稳妥做法:用
asyncio.to_thread()(Python 3.9+)或loop.run_in_executor()显式调度协程到线程中执行 - ❌ 错误示范:
background_tasks.add_task(my_async_func)—— 会崩溃
后台任务失败时默认静默丢弃
BackgroundTasks 不捕获、不传播、不记录异常。函数里抛了 Exception,你收不到任何提示,日志里也不会出现堆栈 —— 除非你自己加 try/except。
- 必须在后台函数内部做错误兜底,比如写入日志文件或发告警
- 不要依赖
BackgroundTasks自带的“重试”——它根本没有重试机制 - 若需可靠执行(如扣款后发短信),
BackgroundTasks不够用,该上Celery或Redis Queue
任务生命周期绑定请求上下文,无法跨请求共享状态
BackgroundTasks 实例随每个请求创建,任务函数运行在线程中,不继承主线程的 Request、DB session 或 contextvars —— 尤其注意数据库连接对象可能已关闭。
- 避免直接传
session或request.state这类生命周期短的对象 - 需要 DB 操作?传
user_id或order_id,让后台函数自己新建 session - 想用
contextvars透传数据?得手动copy_context()+run(),否则变量丢失
真正需要“优雅”的异步后台任务,不是靠 BackgroundTasks 做缝合,而是从设计上区分场景:短时、可丢弃、无状态的任务用它;其余一律交给专业队列。这点容易被文档里“简单易用”的描述带偏。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











