Python中ThreadPool.starmap仅捕获首个异常的原因解析
ThreadPool.starmap仅捕获第一个异常的原因分析
问题现象
使用ThreadPool.starmap执行多线程任务时,仅会捕获并打印第一个抛出的SQLQueryError异常,后续任务虽继续执行但其余异常未被捕获。当在func函数内部添加try-except语句后,所有异常均可被处理。
原代码
from multiprocessing.pool import ThreadPool class SQLQueryError(Exception): def __init__(self, message): self.message = message super().__init__(f"SQL query error: {message}") def solve(args): with ThreadPool(len(args)) as pool: try: return pool.starmap(func,args) except Exception as e: print(e) def func(a, b): if(a=="12" or a=="23" or b == "Work"): raise SQLQueryError( f"Table does not exist {a} and {b}") li = [("12", "Hello"), ("23", "World"), ("12", "Hospital"),("7","Work")] solve(li)
当前输出
SQL query error: Table does not exist 12 and Hello
预期结果
捕获并输出所有抛出的异常内容
原因分析
ThreadPool.starmap的核心机制是:启动所有线程任务后,会等待所有任务完成并收集结果返回,但只要有任意一个任务抛出未捕获的异常,starmap会立即将该异常抛出到调用方的上下文。此时上层的try-except会立刻触发except分支处理这个异常,不再等待后续任务的执行结果,因此后续任务的异常无法被上层的try-except捕获。- 注意:后续任务并不会因为第一个异常抛出而停止执行(因为线程已经启动),只是它们的异常没有被传递到上层上下文,自然无法被捕获打印。
- 当在
func内部添加try-except时,每个线程任务的异常被内部处理,不会将异常抛出到starmap的上下文中,starmap可以正常收集所有任务的执行结果,因此所有异常都能被处理。
内容的提问来源于stack exchange,提问作者Sharanya Bajpai
相关产品推荐
相关产品推荐

