Exception handling in concurrent.futures.Executor.map

user1008636 picture user1008636 · Jun 27, 2018 · Viewed 8.4k times · Source

From https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.Executor.map

If a func call raises an exception, then that exception will be raised when its value is retrieved from the iterator.

The following snippet only outptus the first exeption (Exeption: 1), and stops. Does this contradict the above statement? I expect the following to print out all exceptions in the loop.

def test_func(val):
  raise Exception(val)        

with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:   
  for r in executor.map(test_func,[1,2,3,4,5]):
    try:
      print r
    except Exception as exc:
      print 'generated an exception: %s' % (exc)

Answer

Ehsan Kia picture Ehsan Kia · Nov 16, 2018

As mentioned above, unfortunately executor.map's API is limited and only lets you get the first exception. Also, when iterating through the results, you will only get values up to the first exception.

To answer your question, if you don't wan to use a different library, you can unroll your map and manually apply each function:

future_list = []
with concurrent.futures.ThreadPoolExecutor() as executor:
  for arg in range(10):
    future = executor.submit(test_func, arg)
    future_list.append(future)

for future in future_list:
  try:
    print(future.result())
  except Exception as e:
    print(e)

This allows you to handle each future individually.