Skip to main content
 首页 » 编程设计

python之concurrent.futures.ThreadPoolExecutor 吞噬异常(Python 3.6)

2025年05月04日28wuhuacong

我正在尝试在 Windows 7 上的 Python 3.6 中使用 ThreadPoolExecutor,异常似乎被忽略或停止程序执行。示例代码:

#!/usr/bin/env python3 
 
from time import sleep 
 
from concurrent.futures import ThreadPoolExecutor 
 
EXECUTOR = ThreadPoolExecutor(2) 
 
 
def run_jobs(): 
    EXECUTOR.submit(some_long_task1) 
    EXECUTOR.submit(some_long_task2, 'hello', 123) 
    return 'Two jobs was launched in background!' 
 
 
def some_long_task1(): 
    print("Task #1 started!") 
    for i in range(10000000): 
        j = i + 1 
    1/0 
    print("Task #1 is done!") 
 
 
def some_long_task2(arg1, arg2): 
    print("Task #2 started with args: %s %s!" % (arg1, arg2)) 
    for i in range(10000000): 
        j = i + 1 
    print("Task #2 is done!") 
 
 
if __name__ == '__main__': 
    run_jobs() 
    while True: 
        sleep(1) 

输出:

Task #1 started! 
Task #2 started with args: hello 123! 
Task #2 is done! 

它一直卡在那里,直到我用 Ctrl+C 杀死它。

但是,当我从 some_long_task1 中删除 1/0 时,任务 #1 顺利完成:

Task #1 started! 
Task #2 started with args: hello 123! 
Task #1 is done! 
Task #2 is done! 

我需要捕获在 ThreadPoolExecutor 中运行的函数中引发的异常以某种方式。

Python 3.6 (Minconda),Windows 7 x64。

请您参考如下方法:

ThreadPoolExecutor.submit返回 future object表示计算结果,一旦可用。为了不忽略作业引发的异常,您需要实际访问此结果。首先,您可以更改 run_job 以返回创建的 future :

def run_jobs(): 
    fut1 = EXECUTOR.submit(some_long_task1) 
    fut2 = EXECUTOR.submit(some_long_task2, 'hello', 123) 
    return fut1, fut2 

然后,有顶层代码wait为 future 完成,并访问他们的结果:

import concurrent.futures 
 
if __name__ == '__main__': 
    futures = run_jobs() 
    concurrent.futures.wait(futures) 
    for fut in futures: 
        print(fut.result()) 

在执行引发异常的 future 调用 result() 会将异常传播给调用者。在这种情况下,ZeroDivisionError 将在顶层引发。