Function apply_async of multiprocessing.Pool class has argument error_callback in Python 3. But this argument is missing in <
Instead of adding extra arguments to return, use the successful() method that AnycResult objects provide you. That's what it's there for.
Calls to apply_async return an AsyncResult object. These objects have a method called successful() that will tell you if the target process exited via an exception. Calling successful() will return true or false depending on whether the subprocess exited with an exception. Here is an example:
import multiprocessing
def good_func(arg):
arg += 1
return arg
def bad_func(arg):
arg += 1
raise Exception # force an exception to be raised
return arg
pool = multiprocessing.Pool()
good_result = pool.apply_async(good_func, (1,))
bad_result = pool.apply_async(bad_func, (1,))
pool.close()
pool.join()
print(good_result.successful()) # prints True
print(bad_result.successful()) # prints False
This code returns:
True
False
You can then add a conditional expression that calls your cleanup or error handling code if the call to successfull() returns false.
Furthermore, if you need the traceback, you can wrap the body of your subprocess function in a try/except block and return a string version of the traceback in the event of an exception. It could look something like this version of bad_func:
import sys
import traceback
import multiprocessing
def good_func(arg):
arg += 1
return arg
def bad_func(arg):
try:
arg += 1
raise Exception
return a
except Exception as error:
# capture the exception and bundle the traceback
# in a string, then raise new exception with the string traceback
raise Exception("".join(traceback.format_exception(*sys.exc_info())))
pool = multiprocessing.Pool()
good_result = pool.apply_async(good_func, (1,))
bad_result = pool.apply_async(bad_func, (1,))
pool.close()
pool.join()
print(good_result.successful()) # prints True
print(good_result.get()) # prints good result
print(bad_result.successful()) # prints False
print(bad_result.get()) # prints traceback
This code produces this output:
True
2
False
Traceback (most recent call last):
File "async_err.py", line 29, in
print(bad_result.get())
File "/user/peteoss/encap/Python-2.7.6/lib/python2.7/multiprocessing /pool.py", line 554, in get
raise self._value
Exception: Traceback (most recent call last):
File "async_err.py", line 13, in bad_func
raise Exception
Exception
You should note a few things:
You will get two tracebacks: one from the failed called to get(), and the second one is the traceback that you bundled into a string in your subprocess.
If you wrap the subprocess function in a try/except block, you will need to reraise an exception when you handle it, otherwise get() will return false.
The AsyncResult.successful() and AsyncResult.get() methods are available in all versions of CPython that have the multiprocessing library, so this method meets your requirement of writing version-agnostic code.