当一个线程发生故障时终止多线程代码的正确方法是什么?

时间:2018-09-04 14:15:52

标签: python multithreading

我有以下代码:

def getdata3(self, page, data, apifolder, additional):
    tries = 10
    for n in range(tries):
        try:
        except (ChunkedEncodingError, requests.exceptions.HTTPError) as e:
            ...

            if n == tries - 1:
                raise e            # If arrived here - Terminate !
    print ("{2} page {0} finished. Length is {1}".format(page,len(datarALL),str(datetime.now())))
    return job

主要代码:

    with ThreadPoolExecutor(max_workers=num_of_workers) as executor:
        futh = [(executor.submit(self.getdata3, page, data, apifolder,additional)) for page in pages]
        for data in as_completed(futh):
            datarALL.extend(data.result())
    print ("Finished generateing data.")
    return datarALL

此代码为工作人员创建线程。完成所有工作后,它返回datarALL

我的问题:

我想要的是如果其中一个线程到达这里:

if n == tries - 1:
    raise e            # If arrived here - Terminate !

所有现有线程将被终止。以后将不会创建任何线程(终止for page in pages循环),并且整个程序也将终止。

我阅读了一些有关此问题的文章。我也读过这个Should I use Events, Semaphores, Locks, Conditions, or a combination thereof to manage safely exiting my multithreaded Python program?,但提供的解决方案非常复杂,似乎添加了很多我怀疑我需要的代码。

我试图做:

if n == tries - 1:
    exit(1)      

但是当我检查htop时,并不能关闭整个进程和线程。.我剩下一些遗留下来的僵尸了。

我的问题: 有没有简单,干净的解决方案来终止程序并显示错误通知?

1 个答案:

答案 0 :(得分:3)

sys.exit()有时会卡住,因为它试图正常退出。

一些快速且肮脏的解决方案意味着使用os._exit(1)(1是可能的返回码,指示错误,0表示成功,您不想在这里使用它。请保持在0-255范围内以避免可移植性问题)

在现代系统上,会发生资源跟踪并退出程序,从而杀死所有附加资源(文件句柄,线程,内存...),因此这是一个可接受的解决方案。

缺点是它绕过python退出/清理程序,就像您使用kill杀死python进程时一样。在缺乏资源跟踪管理的操作系统上(我们正在谈论古老的历史),这将导致全局内存泄漏/文件描述符。

对于您而言,这并不重要,因为没有此权限,您将无法退出应用程序。但是不要一概而论,将其保留用于紧急出口程序。