while True:
    item = q.get()
    handle(item)
    q.task_done()  # 每条都必须调

生产者放完数据调 queue.join() 等消费完成,主进程一直挂着,子进程日志显示数据早就处理完,程序就是不往下走。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。

原因不复杂,join 等的是未完成任务计数归零,消费者每取一条必须调一次 task_done,漏一条计数就永远减不到零,主进程只能一直等下去,并且没有任何报错。

「多进程队列死锁」改完先别急着全量,挑一台机器放半天,真有问题这段时间就能看出来。改动写完就同步给同事,下一个人踩同一个坑,成本还是你的。

验证用真实数据走一遍,测试数据太干净,边界情况根本碰不到。

处理上按这个顺序:消费者用 try/finally 保证每条都调一次 task_done,异常分支也不例外;异常分支也要计数,别让坏数据把计数卡住,拿不到结果也要归还;调试时打印未完成任务计数,看看到底还剩几条没有归还。

改完只确认一件事:join 在数据处理完之后几秒内返回,未完成任务计数归零,不再挂住主进程。

作者 9823189