从Python中的线程引发多个异常

时间:2013-08-16 22:14:01

标签: python exception

tl; dr我产生3个线程,每个线程抛出异常,大多数pythonic方式引发所有3个异常?

下面是一个与我正在做的类似的代码示例。

from multiprocessing.pool import ThreadPool

def fail_func(host):
    raise Exception('{} FAILED!!!'.format(host))

hosts = ['172.1.1.1', '172.1.1.2', '172.1.1.3']
pool = ThreadPool(processes=5)
workers = [pool.apply_async(fail_func(host)) for host in hosts]
# join and close thread pool
pool.join(); pool.close()
# get the exceptions
[worker.get() for worker in workers if not worker.successful()]

它最终做的只是在第一台主机上失败,并带有以下追溯:

Traceback (most recent call last):
  File "thread_exception_example.py", line 8, in <module>
    workers = [pool.apply_async(fail_func(host)) for host in hosts]
  File "thread_exception_example.py", line 4, in fail_func
    raise Exception('{} FAILED!!!'.format(host))
Exception: 172.1.1.1 FAILED!!!

但我想要它做的是为每个失败的线程引发多个异常,如下所示:

Traceback (most recent call last):
  File "thread_exception_example.py", line 8, in <module>
    workers = [pool.apply_async(fail_func(host)) for host in hosts]
  File "thread_exception_example.py", line 4, in fail_func
    raise Exception('{} FAILED!!!'.format(host))
Exception: 172.1.1.1 FAILED!!!

Traceback (most recent call last):
  File "thread_exception_example.py", line 8, in <module>
    workers = [pool.apply_async(fail_func(host)) for host in hosts]
  File "thread_exception_example.py", line 4, in fail_func
    raise Exception('{} FAILED!!!'.format(host))
Exception: 172.1.1.2 FAILED!!!

Traceback (most recent call last):
  File "thread_exception_example.py", line 8, in <module>
    workers = [pool.apply_async(fail_func(host)) for host in hosts]
  File "thread_exception_example.py", line 4, in fail_func
    raise Exception('{} FAILED!!!'.format(host))
Exception: 172.1.1.3 FAILED!!!

有没有pythonic方式这样做?或者我是否需要在try / except中包装所有内容,收集所有消息,然后重新引发单个异常?

1 个答案:

答案 0 :(得分:2)

没有办法“提出多个例外”。在给定的异常上下文中,是否存在异常。

所以是的,您将不得不创建一个包含所有异常的包装器异常,然后提高它。但是你几乎得到了所需的所有代码:

def get_exception():
    try:
        worker.get()
    except Exception as e:
        return e

现在,而不是:

[worker.get() for worker in workers if not worker.successful()]

......你可以这样做:

[get_exception(worker.get) for worker in workers if not worker.successful()]

这是一系列例外情况。


就我个人而言,我一直认为AsyncResult应该有exception方法,类似于concurrent.futures.Future中的方法。但是我首先会在这里使用futures(如果我被迫使用Python 2.x,则安装backport。)