Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

concurrent.futures.ThreadPoolExecutor swallowing exceptions (Python 3.6)

I'm trying to use ThreadPoolExecutor in Python 3.6 on Windows 7 and it seems that the exceptions are silently ignored or stop program execution. Example code:

#!/usr/bin/env python3

from time import sleep

from concurrent.futures import ThreadPoolExecutor

EXECUTOR = ThreadPoolExecutor(2)


def run_jobs():
    EXECUTOR.submit(some_long_task1)
    EXECUTOR.submit(some_long_task2, 'hello', 123)
    return 'Two jobs was launched in background!'


def some_long_task1():
    print("Task #1 started!")
    for i in range(10000000):
        j = i + 1
    1/0
    print("Task #1 is done!")


def some_long_task2(arg1, arg2):
    print("Task #2 started with args: %s %s!" % (arg1, arg2))
    for i in range(10000000):
        j = i + 1
    print("Task #2 is done!")


if __name__ == '__main__':
    run_jobs()
    while True:
        sleep(1)

The output:

Task #1 started!
Task #2 started with args: hello 123!
Task #2 is done!

It's hanging there until I kill it with Ctrl+C.

However, when I remove 1/0 from some_long_task1, Task #1 completes without problem:

Task #1 started!
Task #2 started with args: hello 123!
Task #1 is done!
Task #2 is done!

I need to capture the exceptions raised in functions running in ThreadPoolExecutor somehow.

Python 3.6 (Minconda), Windows 7 x64.

like image 615
LetMeSOThat4U Avatar asked Mar 16 '18 13:03

LetMeSOThat4U


People also ask

What is ThreadPoolExecutor in Python?

The ThreadPoolExecutor allows you to create and manage thread pools in Python. Although the ThreadPoolExecutor has been available since Python 3.2, it is not widely used, perhaps because of misunderstandings of the capabilities and limitations of Threads in Python.

What is Python concurrent futures?

The concurrent. futures module provides a high-level interface for asynchronously executing callables. The asynchronous execution can be performed with threads, using ThreadPoolExecutor , or separate processes, using ProcessPoolExecutor .

Is ThreadPoolExecutor thread safe python?

ThreadPoolExecutor Thread-Safety Although the ThreadPoolExecutor uses threads internally, you do not need to work with threads directly in order to execute tasks and get results. Nevertheless, when accessing resources or critical sections, thread-safety may be a concern.

Is concurrent futures thread safe?

Yes, it's thread-safe.


1 Answers

ThreadPoolExecutor.submit returns a future object that represents the result of the computation, once it's available. In order to not ignore the exceptions raised by the job, you need to actually access this result. First, you can change run_job to return the created futures:

def run_jobs():
    fut1 = EXECUTOR.submit(some_long_task1)
    fut2 = EXECUTOR.submit(some_long_task2, 'hello', 123)
    return fut1, fut2

Then, have the top-level code wait for the futures to complete, and access their results:

import concurrent.futures

if __name__ == '__main__':
    futures = run_jobs()
    concurrent.futures.wait(futures)
    for fut in futures:
        print(fut.result())

Calling result() on a future whose execution raised an exception will propagate the exception to the caller. In this case the ZeroDivisionError will get raised at top-level.

like image 175
user4815162342 Avatar answered Sep 30 '22 10:09

user4815162342