Ответ 1
Как указано в документах, ошибка таймаута будет повышаться только в том случае, если вы вызываете метод __next__()
на карте. Чтобы вызвать этот метод, вы можете, например, преобразовать вывод в список:
from concurrent import futures
import threading
import time
def task(n):
print("Launching task {}".format(n))
time.sleep(n)
print('{}: done with {}'.format(threading.current_thread().name, n))
return n / 10
with futures.ThreadPoolExecutor(max_workers=5) as ex:
results = ex.map(task, range(1, 6), timeout=3)
print('main: starting')
try:
# without this conversion to a list, the timeout error is not raised
real_results = list(results)
except futures._base.TimeoutError:
print("TIMEOUT")
Выход:
Launching task 1
Launching task 2
Launching task 3
Launching task 4
Launching task 5
ThreadPoolExecutor-9_0: done with 1
ThreadPoolExecutor-9_1: done with 2
TIMEOUT
ThreadPoolExecutor-9_2: done with 3
ThreadPoolExecutor-9_3: done with 4
ThreadPoolExecutor-9_4: done with 5
Здесь n-я задача засыпает в течение n
секунд, поэтому тайм-аут поднимается после завершения задания 2.
EDIT: Если вы хотите завершить задачи, которые не были выполнены, вы можете попробовать ответы в этом вопросе (они не используют ThreadPoolExecutor.map()
хотя), или вы можете просто игнорировать возвращаемые значения из других задач и пусть они закончат:
from concurrent import futures
import threading
import time
def task(n):
print("Launching task {}".format(n))
time.sleep(n)
print('{}: done with {}'.format(threading.current_thread().name, n))
return n
with futures.ThreadPoolExecutor(max_workers=5) as ex:
results = ex.map(task, range(1, 6), timeout=3)
outputs = []
try:
for i in results:
outputs.append(i)
except futures._base.TimeoutError:
print("TIMEOUT")
print(outputs)
Выход:
Launching task 1
Launching task 2
Launching task 3
Launching task 4
Launching task 5
ThreadPoolExecutor-5_0: done with 1
ThreadPoolExecutor-5_1: done with 2
TIMEOUT
[1, 2]
ThreadPoolExecutor-5_2: done with 3
ThreadPoolExecutor-5_3: done with 4
ThreadPoolExecutor-5_4: done with 5