检查 python 线程是否抛出异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18349614/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 10:32:24  来源:igfitidea点击:

Check if a python thread threw an exception

pythonmultithreadingexceptionexception-handling

提问by Nathan Williams

I have a set of tasks to do in parallel, but at the end of them, I need to know if any of the threads threw an exception. I don't need to handle the exception directly, I just need to know if one of the threads failed with an exception, so I can cleanly terminate the script

我有一组任务要并行执行,但在它们结束时,我需要知道是否有任何线程抛出异常。我不需要直接处理异常,我只需要知道其中一个线程是否因异常而失败,这样我就可以干净地终止脚本

Here is a simple example:

这是一个简单的例子:

#!/usr/bin/python

from time import sleep
from threading import Thread

def func(a):
    for i in range(0,5):
        print a
        sleep(1)

def func_ex():
    sleep(2)
    raise Exception("Blah")


x = [Thread(target=func, args=("T1",)), Thread(target=func, args=("T2",)), Thread(target=func_ex, args=())]

print "Starting"
for t in x:
    t.start()

print "Joining"
for t in x:
    t.join()


print "End"

Before "End", I want to iterate through the threads, see if any failed, and then decide if I can continue with the script, or if I need to exit at this point.

在“结束”之前,我想遍历线程,看看是否有任何失败,然后决定是否可以继续执行脚本,或者此时是否需要退出。

I don't need to intercept the exception or stop the other threads, I just need to know at the end if any failed.

我不需要拦截异常或停止其他线程,我只需要最后知道是否有任何失败。

采纳答案by Alp

By the time the join()call on a thread returns the thread's stack has been unwound and all information about exceptions has been lost. Thus, unfortunately, you'll need to provide your own mechanism for registering exceptions; some techniques are discussed here.

join()线程调用返回时,线程的堆栈已展开,所有有关异常的信息都已丢失。因此,不幸的是,您需要提供自己的异常注册机制;这里讨论了一些技术。

回答by whitebeard

A simple technique for situations where you do not need to handle the exception is to use a global list and append to it pertinent information. Your code would become something like:

在不需要处理异常的情况下,一种简单的技术是使用全局列表并向其附加相关信息。你的代码会变成这样:

#!/usr/bin/python

from time import sleep
from threading import Thread, current_thread #needed to get thread name or whatever identifying info you need

threadErrors = [] #global list

def func(a):
    for i in range(0,5):
        print a
        sleep(1)

def func_ex():
    global threadErrors #if you intend to change a global variable from within a different scope it has to be declared
    try:
        sleep(2)
        raise Exception("Blah")
    except Exception, e:
        threadErrors.append([repr(e), current_thread.name]) #append a list of info
        raise #re-raise the exception or use sys.exit(1) to let the thread die and free resources 

x = [Thread(target=func, args=("T1",)), Thread(target=func, args=("T2",)), Thread(target=func_ex, args=())]

print "Starting"
for t in x:
    t.start()

print "Joining"
for t in x:
    t.join()

if len(threadErrors) > 0: #check if there are any errors 
    for e in threadErrors:
        print(threadErrors[e][0]+' occurred in thread: '+threadErrors[e][1])
        #do whatever with each error info
else: 
    #there are no errors so do normal clean-up stuff

#do clean-up that should happen in either case here

print "End"

Note:global variables are generally regarded as poor technique, butthey are a simple mechanism for communicating between threads. You just have to remember that if one thread is sending info by this route the other thread has to be looking for it.

注意:全局变量通常被认为是一种糟糕的技术,它们是线程间通信的简单机制。你只需要记住,如果一个线程通过这条路线发送信息,另一个线程必须寻找它。