Процессы в multiprocessing.Pool не сообщают об ошибках времени выполнения

У меня есть пул процессов в python, использующий from multiprocessing import Pool. Я передаю этим процессам различные функции для запуска, вызывая функцию Pool.apply_async. Если я ввожу ошибку в одну из этих функций (например, строку кода, такую ​​как 5/0), ожидаемый отчет командной строки ZeroDivisionError: integer division or modulo by zero никогда не появляется, и программа никогда не завершается. Даже если я введу функцию обратного вызова в вызове Pool.apply_async, функция обратного вызова никогда не будет вызвана, если функция, которую должен выполнить процесс, содержит ошибку.

Как я могу сделать так, чтобы эти процессы в пуле сообщали об ошибках и завершались, если что-то пойдет не так?


person Jadiel de Armas    schedule 08.10.2014    source источник


Ответы (1)


Вы должны попытаться получить get результат из AsyncResult, возвращенного apply_async (или map_async) для исключение, которое должно быть поднято в родительском.

def func():
    raise Exception("We failed")

...
result = pool.apply_async(func, args=(arg))
time.sleep(2)
result.get() # Exception only gets raised here

Любое указанное вами callback выполняется только в случае успешного завершения функции. Он пропускается, если вызывает исключение.

В Python 3.2+ аргумент ключевого слова error_callback был представлен, что позволяет вам передавать обратный вызов, который выполняется, если в рабочем потоке возникает исключение, но вы не можете сделать это в Python 2.x. Что вы можете сделать, так это обернуть свою рабочую функцию в блок try/except, который возвращает любое исключение, сгенерированное в рабочем потоке, а не вызывает его:

def func():
    try:
        raise Exception("We failed")
    except Exception as e:
        return e

Затем у вас может быть обычная функция обратного вызова, которая проверяет, был ли возвращен Exception:

def callback(result):
   if isinstance(result, Exception):
       # Do whatever you need to do to clean up and exit
   else:
       # Function was successful
person dano    schedule 08.10.2014
comment
Отлично подходит для вашей информации. Большое спасибо! Думаю, я перейду на python 3.2, чтобы все было проще. - person Jadiel de Armas; 08.10.2014
comment
@ASDF Я бы порекомендовал перейти на 3.4, если это возможно (это намного новее), но да, Python 3.x облегчит вам жизнь здесь. Если портировать вашу программу не слишком сложно, дерзайте. - person dano; 08.10.2014