asyncio.Queue本身不支持权重,需自行封装调度逻辑:可用多队列+权重轮询、统一队列+权重感知消费者,或主fetcher按归一化权重比例主动拉取任务,并注意异常处理、动态权重更新的线程安全。

asyncio.Queue 本身不支持权重,得自己封装调度逻辑
Python 标准库的 asyncio.Queue 是 FIFO 的,没有优先级或权重机制。想按权重分发任务(比如高权重任务更快被取走、更多并发执行),必须在消费者端做调度判断,不能依赖队列底层。
常见错误是试图给 asyncio.Queue.put() 加 weight 参数——它不接受;或者误以为 asyncio.PriorityQueue 能直接用于权重调度——它只按数字大小排序,且不解决“高权重任务应获得更高并发配额”这个核心诉求。
- 权重不是简单的“谁先跑”,而是影响任务获取频率和协程分配比例
- 推荐用一个带权重的轮询器 + 多个
asyncio.Queue实例(每类权重一个队列),或统一队列 + 权重感知的消费者 - 若权重是浮点数(如 0.3、1.5),建议先归一化为整数倍数(如 ×10 → 3、15),避免浮点精度干扰调度公平性
用 asyncio.create_task + 权重感知的 fetcher 循环
最可控的做法是不依赖队列的自动调度,而由一个主 fetcher 协程主动按权重比例拉取任务。假设你有三类任务:high(权重 3)、medium(权重 2)、low(权重 1),目标是让 high 类任务平均获得 50% 的处理机会(3 / (3+2+1))。
示例结构:
weight_map = {"high": 3, "medium": 2, "low": 1}
queues = {
"high": asyncio.Queue(),
"medium": asyncio.Queue(),
"low": asyncio.Queue()
}
<p>async def weighted_fetcher():
while True:</p><h1>按权重随机选择队列(可替换为轮询或累积概率)</h1><pre class="brush:python;toolbar:false;"> choices = []
for k, w in weight_map.items():
choices.extend([k] * w)
queue_key = random.choice(choices)
try:
task = await queues[queue_key].get()
asyncio.create_task(run_task(task))
except asyncio.QueueEmpty:
continue
await asyncio.sleep(0) # 让出控制权,避免忙等
注意:asyncio.Queue.get() 是阻塞式等待,但这里用 try/except + await asyncio.sleep(0) 避免卡死空队列;真实场景中建议加超时或改用 asyncio.wait_for(q.get(), timeout=0.1) 防止饿死低权重队列。
避免 asyncio.gather 吞掉异常导致权重调度失效
很多人会把一批任务丢进 asyncio.gather() 并设 return_exceptions=True,但这会让所有任务“平权”并发,完全绕过权重逻辑。一旦用了 gather,权重就只体现在提交顺序上,而非运行时资源分配。
- 权重调度必须在任务创建(
create_task)前决策,而不是在批量 await 时补救 - 如果要用
gather,只能按权重分批调用,比如先 gather 3 个 high,再 2 个 medium,再 1 个 low —— 但这样失去动态性,且无法应对队列实时变化 - 更糟的是:
gather中某个任务抛异常后,若没设return_exceptions=True,整个批次中断,后续权重任务全被跳过
权重变更需原子更新,否则引发竞态
如果运行时需要调整某类任务的权重(比如突发流量下临时提升 high 权重),不能直接改 weight_map["high"] = 5 —— 多个 fetcher 协程可能正在读这个字典,造成新旧权重混用。
正确做法:
- 用
asyncio.Lock包裹权重读写,但锁粒度太大会降低调度吞吐 - 更轻量:用
asyncio.Queue或asyncio.Event触发权重热更新,fetcher 主循环定期检查版本号或监听更新信号 - 极端情况(如毫秒级敏感调度)建议用
threading.local()+loop.run_in_executor隔离权重状态,但 Python 异步生态里这属于过度设计
真正难的不是实现权重,而是让权重在高并发、动态变化、异常频发的场景下依然保持可预期的倾斜比例——这点很容易被本地测试忽略。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











