asyncio.Queue 是原生协程安全的轻量内存队列,需在同事件循环中使用,支持背压但无持久化;正确用法是 producer/consumer 模式配合 task_done() 和 join(),须设 maxsize 防 OOM。

asyncio.Queue 就是你要的轻量队列
不用装第三方包,asyncio.Queue 原生支持协程间安全的数据传递,内存驻留、无序列化开销、启动零成本。它不是“模拟”队列,而是 asyncio 事件循环原生调度的同步原语。
常见错误是拿它当线程安全队列用——比如在 threading.Thread 里调用 await queue.put(),这会直接报 RuntimeError: no running event loop。它只在协程上下文里有效。
- 必须在同一个
asyncio.EventLoop中使用(通常就是主协程或同个asyncio.create_task()启动的任务) -
maxsize=0(默认)表示无限制;设为正整数后,put()在满时会 await,自动实现背压 - 不支持持久化、不跨进程、不跨解释器——就是纯内存+协程协作
如何启动一个持续消费任务的 worker
别写死循环加 sleep(),那会阻塞事件循环。正确做法是用 async for 或持续 await queue.get(),让出控制权给其他协程。
典型结构是:一个 producer 协程不断 await queue.put(item),一个或多个 consumer 协程用 while True: + await queue.get() 拉取并处理。
立即学习“Python免费学习笔记(深入)”;
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 记得调用
queue.task_done(),否则queue.join()永远不会返回 - consumer 内部异常要捕获,否则任务崩溃后整个 worker 就静默退出了
- 如果想优雅停止,可以用
asyncio.Event配合queue.get_nowait()或超时await asyncio.wait_for(queue.get(), timeout=1)
async def worker(queue: asyncio.Queue):
while True:
try:
item = await queue.get()
await process(item) # 实际异步处理
except Exception as e:
print(f"failed on {item}: {e}")
finally:
queue.task_done()为什么不用 asyncio.create_task() 直接并发,而要加 Queue
直接 create_task() 是发散式并发,缺乏节流、优先级、重试、顺序保证等控制能力。Queue 提供的是“受控流水线”:生产者不关心谁消费,消费者不感知谁生产,中间靠容量和阻塞自然协调节奏。
比如爬虫场景:你有 100 个 URL 要 fetch,但不想同时发起 100 个请求压垮目标站。这时设 asyncio.Queue(maxsize=5),配合 5 个常驻 worker,天然实现并发限流。
- 没 Queue 时,容易写出
[asyncio.create_task(fetch(u)) for u in urls]—— 瞬间全发出去,失去控制 - Queue 的
join()可精确等待所有已入队任务完成,比asyncio.gather()更适合动态增删任务的场景 - 注意:Queue 本身不提供失败重试逻辑,得自己在 consumer 里封装
内存泄漏和积压风险在哪
最常被忽略的是:producer 快、consumer 慢,又没设 maxsize,队列无限增长,最终 OOM。这不是 asyncio 的 bug,是设计使然——它默认信任你对流量的掌控。
另一个坑是 consumer 挂了没重启,但 producer 还在 push,数据就卡在内存里没人取。没有 broker 的兜底机制,这类问题只能靠监控 + 主动探测。
- 上线前必设
maxsize,哪怕只是 1000,也比 0 安全 - 定期用
queue.qsize()打点(注意:非原子操作,仅作估算) - 避免在
queue.put()前做耗时同步操作(如 JSON 序列化),否则会拖慢 producer 协程,间接加剧积压
异步队列的“轻量”,本质是把复杂性交还给了使用者:它不帮你存盘、不替你重试、不给你 Web UI。能接受这点,它就真轻;想让它变重,那就该换 Celery 或 Dramatiq 了。

















