Перейти к содержимому

concurrent.futures – Запуск параллельных задач

Добавлено в версии 3.2.

Исходный код: Lib/concurrent/futures/thread.py, Lib/concurrent/futures/process.py, и Lib/concurrent/futures/interpreter.py


Модуль concurrent.futures предоставляет высокоуровневый интерфейс для асинхронного выполнения вызываемых объектов.

Асинхронное выполнение может быть выполнено с помощью потоков, используя ThreadPoolExecutor или InterpreterPoolExecutor, или отдельных процессов, используя ProcessPoolExecutor. Каждый реализует один и тот же интерфейс, который определён абстрактным классом Executor.

concurrent.futures.Future не следует путать с asyncio.Future, который предназначен для использования с asyncio задачами и корутинами. См. документацию asyncio’s Future для подробного сравнения этих двух.

Доступность: не WASI.

Этот модуль не работает или недоступен на WebAssembly. См. платформы WebAssembly для получения дополнительной информации.

Executor ObjectsОбъекты исполнителя

class concurrent.futures.Executor

Абстрактный класс, предоставляющий методы для асинхронного выполнения вызовов. Его не следует использовать напрямую, а только через его конкретные подклассы.

submit(fn, /, *args, **kwargs)

Планирует выполнение вызываемого объекта fn как fn(*args, **kwargs) и возвращает объект Future, представляющий выполнение вызываемого объекта.

python
with ThreadPoolExecutor(max_workers=1) as executor:
    future = executor.submit(pow, 323, 1235)
    print(future.result())
map(fn, *iterables, timeout=None, chunksize=1, buffersize=None)

Аналогично map(fn, *iterables), за исключением:

  • iterables собираются сразу, а не лениво, если не указан buffersize для ограничения количества отправленных задач, результаты которых ещё не были получены. Если буфер полон, итерация по iterables приостанавливается, пока результат не будет получен из буфера.

  • fn выполняется асинхронно, и несколько вызовов fn могут быть выполнены одновременно.

Возвращаемый итератор вызывает TimeoutError, если __next__() вызывается и результат недоступен через timeout секунд после исходного вызова Executor.map(). timeout может быть int или float. Если timeout не указан или None, время ожидания не ограничено.

Если вызов fn вызывает исключение, то это исключение будет возбуждено при извлечении его значения из итератора.

При использовании ProcessPoolExecutor этот метод разбивает итерируемые объекты на несколько фрагментов, которые отправляет в пул как отдельные задачи. Приблизительный размер этих фрагментов можно задать, установив chunksize в положительное целое число. Для очень длинных итерируемых объектов использование большого значения chunksize может значительно повысить производительность по сравнению с размером по умолчанию 1. С ThreadPoolExecutor и InterpreterPoolExecutor параметр chunksize не действует.

Изменено в версии 3.5: Добавлен параметр chunksize.

Изменено в версии 3.14: Добавлен параметр buffersize.

shutdown(wait=True, *, cancel_futures=False)

Сигнализирует исполнителю, что он должен освободить все используемые ресурсы, когда текущие ожидающие futures завершат выполнение. Вызовы Executor.submit() и Executor.map(), сделанные после shutdown, возбудят RuntimeError.

Если wait равно True, то этот метод не вернется, пока все ожидающие futures не завершат выполнение и ресурсы, связанные с исполнителем, не будут освобождены. Если wait равно False, то этот метод вернется немедленно, а ресурсы, связанные с исполнителем, будут освобождены по завершении всех ожидающих futures. Независимо от значения wait, вся программа Python не завершится, пока все ожидающие futures не завершат выполнение.

Если cancel_futures равно True, этот метод отменит все ожидающие futures, которые исполнитель еще не начал выполнять. Любые futures, которые завершены или выполняются, не будут отменены, независимо от значения cancel_futures.

Если оба cancel_futures и wait равны True, все futures, которые исполнитель начал выполнять, будут завершены до возврата этого метода. Остальные futures отменяются.

Вы можете избежать необходимости явного вызова этого метода, если используете исполнитель как менеджер контекста через оператор with, который завершит работу Executor (ожидая так, как если бы Executor.shutdown() был вызван с wait, установленным в True):

python
import shutil
with ThreadPoolExecutor(max_workers=4) as e:
    e.submit(shutil.copy, 'src1.txt', 'dest1.txt')
    e.submit(shutil.copy, 'src2.txt', 'dest2.txt')
    e.submit(shutil.copy, 'src3.txt', 'dest3.txt')
    e.submit(shutil.copy, 'src4.txt', 'dest4.txt')

Изменено в версии 3.9: Добавлен cancel_futures.

ThreadPoolExecutor

ThreadPoolExecutor является подклассом Executor, который использует пул потоков для асинхронного выполнения вызовов.

Взаимные блокировки могут возникать, когда вызываемый объект, связанный с Future, ожидает результатов другого Future. Например:

python
import time
def wait_on_b():
    time.sleep(5)
    print(b.result())  # b никогда не завершится, потому что ожидает a.
    return 5

def wait_on_a():
    time.sleep(5)
    print(a.result())  # a никогда не завершится, потому что ожидает b.
    return 6


executor = ThreadPoolExecutor(max_workers=2)
a = executor.submit(wait_on_b)
b = executor.submit(wait_on_a)

И:

python
def wait_on_future():
    f = executor.submit(pow, 5, 2)
    # Это никогда не завершится, потому что есть только один рабочий поток и
    # он выполняет эту функцию.
    print(f.result())

executor = ThreadPoolExecutor(max_workers=1)
future = executor.submit(wait_on_future)
# Примечание: вызов future.result() также вызовет взаимоблокировку, потому что
# единственный рабочий поток уже ожидает wait_on_future().
class concurrent.futures.ThreadPoolExecutor(max_workers=None, thread_name_prefix='', initializer=None, initargs=())

Подкласс Executor, который использует пул не более чем из max_workers потоков для асинхронного выполнения вызовов.

Все потоки, поставленные в очередь ThreadPoolExecutor, будут присоединены до выхода интерпретатора. Обратите внимание, что обработчик выхода, который это делает, выполняется до любых обработчиков выхода, добавленных с помощью atexit. Это означает, что исключения в главном потоке должны быть перехвачены и обработаны, чтобы сигнализировать потокам о корректном выходе. По этой причине рекомендуется не использовать ThreadPoolExecutor для долго выполняющихся задач.

initializer – это необязательный вызываемый объект, который вызывается в начале каждого рабочего потока; initargs – это кортеж аргументов, передаваемых инициализатору. Если initializer вызовет исключение, все текущие ожидающие задания возбудят BrokenThreadPool, а также любая попытка отправить новые задания в пул.

Изменено в версии 3.5: Если max_workers равно None или не указано, по умолчанию будет использоваться количество процессоров на машине, умноженное на 5, исходя из того, что ThreadPoolExecutor часто используется для наложения операций ввода-вывода, а не для работы ЦП, и количество рабочих должно быть больше, чем количество рабочих для ProcessPoolExecutor.

Изменено в версии 3.6: Добавлен параметр thread_name_prefix, позволяющий пользователям управлять именами threading.Thread для рабочих потоков, создаваемых пулом, для упрощения отладки.

Изменено в версии 3.7: Добавлены аргументы initializer и initargs.

Изменено в версии 3.8: Значение по умолчанию max_workers изменено на min(32, os.cpu_count() + 4). Это значение по умолчанию сохраняет как минимум 5 рабочих потоков для задач, связанных с вводом-выводом. Оно использует не более 32 ядер ЦП для задач, связанных с ЦП, которые освобождают GIL. И оно позволяет избежать неявного использования очень больших ресурсов на многоядерных машинах.

ThreadPoolExecutor теперь также повторно использует простаивающие рабочие потоки перед запуском max_workers рабочих потоков.

Изменено в версии 3.13: Значение по умолчанию max_workers изменено на min(32, (os.process_cpu_count() or 1) + 4).

ThreadPoolExecutor ExampleПример ThreadPoolExecutor

python
import concurrent.futures
import urllib.request

URLS = ['http://www.foxnews.com/',
        'http://www.cnn.com/',
        'http://europe.wsj.com/',
        'http://www.bbc.co.uk/',
        'http://nonexistent-subdomain.python.org/']

# Получить одну страницу и вывести URL и содержимое
def load_url(url, timeout):
    with urllib.request.urlopen(url, timeout=timeout) as conn:
        return conn.read()

# Мы можем использовать оператор with, чтобы гарантировать своевременную очистку потоков
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
    # Запустить операции загрузки и пометить каждый future его URL
    future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}
    for future in concurrent.futures.as_completed(future_to_url):
        url = future_to_url[future]
        try:
            data = future.result()
        except Exception as exc:
            print('%r generated an exception: %s' % (url, exc))
        else:
            print('%r page is %d bytes' % (url, len(data)))

InterpreterPoolExecutor

Добавлено в версии 3.14.

Класс InterpreterPoolExecutor использует пул интерпретаторов для асинхронного выполнения вызовов. Это подкласс ThreadPoolExecutor, что означает, что каждый рабочий выполняется в собственном потоке. Разница в том, что каждый рабочий имеет собственный интерпретатор и выполняет каждую задачу, используя этот интерпретатор.

Самое большое преимущество использования интерпретаторов вместо только потоков – это настоящая многопоточность на нескольких ядрах. Каждый интерпретатор имеет свою собственную глобальную блокировку интерпретатора, поэтому код, выполняющийся в одном интерпретаторе, может работать на одном ядре ЦП, в то время как код в другом интерпретаторе работает без блокировки на другом ядре.

Обратная сторона в том, что написание параллельного кода для использования с несколькими интерпретаторами может потребовать дополнительных усилий. Однако это связано с тем, что он заставляет вас продумывать, как и когда взаимодействуют интерпретаторы, и явно указывать, какие данные передаются между интерпретаторами. Это дает несколько преимуществ, которые помогают компенсировать дополнительные усилия, включая настоящий параллелизм на нескольких ядрах. Например, код, написанный таким образом, может упростить анализ параллелизма. Еще одно важное преимущество – вам не нужно иметь дело с некоторыми из основных проблем использования потоков, такими как состояния гонки.

Интерпретатор каждого рабочего изолирован от всех других интерпретаторов. «Изолирован» означает, что каждый интерпретатор имеет собственное состояние выполнения и работает полностью независимо. Например, если вы перенаправляете sys.stdout в одном интерпретаторе, это не будет автоматически перенаправлено в любой другой интерпретатор. Если вы импортируете модуль в одном интерпретаторе, он не будет автоматически импортирован в другом. Вам нужно будет импортировать модуль отдельно в интерпретаторе, где он нужен. Фактически, каждый модуль, импортированный в одном интерпретаторе, является полностью отдельным объектом от того же модуля в другом интерпретаторе, включая sys, builtins и даже __main__.

Изоляция означает, что изменяемый объект или другие данные не могут использоваться более чем одним интерпретатором одновременно. Это фактически означает, что интерпретаторы не могут совместно использовать такие объекты или данные. Вместо этого каждый интерпретатор должен иметь свою собственную копию, и вам придется вручную синхронизировать любые изменения между копиями. Неизменяемые объекты и данные, такие как встроенные синглтоны, строки и кортежи неизменяемых объектов, не имеют этих ограничений.

Наиболее эффективно общаться и синхронизироваться между интерпретаторами с помощью специализированных инструментов, например тех, что предложены в PEP 734. Менее эффективная альтернатива – сериализовать с помощью pickle, а затем передать байты через общий socket или pipe.

class concurrent.futures.InterpreterPoolExecutor(max_workers=None, thread_name_prefix='', initializer=None, initargs=())

Подкласс ThreadPoolExecutor, который выполняет вызовы асинхронно, используя пул из не более чем max_workers потоков. Каждый поток выполняет задачи в своем собственном интерпретаторе. Рабочие интерпретаторы изолированы друг от друга, что означает, что каждый имеет собственное состояние времени выполнения и не может совместно использовать изменяемые объекты или другие данные. Каждый интерпретатор имеет свою собственную Глобальную блокировку интерпретатора, что означает, что код, выполняемый с помощью этого исполнителя, обладает истинной многоядерной параллельностью.

Необязательные аргументы initializer и initargs имеют тот же смысл, что и для ThreadPoolExecutor: инициализатор запускается при создании каждого рабочего процесса, однако в данном случае он выполняется в интерпретаторе рабочего процесса. Исполнитель сериализует initializer и initargs с помощью pickle при отправке их в интерпретатор рабочего процесса.

Примечание

Исполнитель может заменять необработанные исключения из initializer на ExecutionFailed.

Другие предостережения из родительского ThreadPoolExecutor применяются и здесь.

submit() и map() работают как обычно, за исключением того, что рабочий процесс сериализует вызываемый объект и аргументы с помощью pickle при отправке их в свой интерпретатор. Рабочий процесс также сериализует возвращаемое значение при отправке его обратно.

Когда текущая задача рабочего процесса вызывает необработанное исключение, рабочий процесс всегда пытается сохранить исключение как есть. Если это удается, то он также устанавливает __cause__ в соответствующий экземпляр ExecutionFailed, который содержит сводку исходного исключения. В редком случае, когда рабочий процесс не может сохранить исходное исключение как есть, он вместо этого напрямую сохраняет соответствующий экземпляр ExecutionFailed.

ProcessPoolExecutor

Класс ProcessPoolExecutor является подклассом Executor, который использует пул процессов для асинхронного выполнения вызовов. ProcessPoolExecutor использует модуль multiprocessing, что позволяет обойти Глобальную блокировку интерпретатора, но также означает, что могут выполняться и возвращаться только объекты, подлежащие пиклованию.

Модуль __main__ должен быть импортируемым рабочими подпроцессами. Это означает, что ProcessPoolExecutor не будет работать в интерактивном интерпретаторе.

Вызов методов Executor или Future из вызываемого объекта, переданного в ProcessPoolExecutor, приведет к взаимоблокировке (deadlock).

Обратите внимание, что ограничения на функции и аргументы, которые должны быть пиклируемыми, согласно multiprocessing.Process, применяются при использовании submit() и map() на ProcessPoolExecutor. Функция, определенная в REPL или лямбда, не должна рассчитывать на работу.

class concurrent.futures.ProcessPoolExecutor(max_workers=None, mp_context=None, initializer=None, initargs=(), max_tasks_per_child=None)

Подкласс Executor, который выполняет вызовы асинхронно, используя пул из не более чем max_workers процессов. Если max_workers равно None или не указано, по умолчанию будет os.process_cpu_count(). Если max_workers меньше или равно 0, будет вызвано ValueError. В Windows max_workers должно быть меньше или равно 61. В противном случае будет вызвано ValueError. Если max_workers равно None, то выбранное по умолчанию значение будет не более 61, даже если доступно больше процессоров. mp_context может быть контекстом multiprocessing или None. Он будет использоваться для запуска рабочих процессов. Если mp_context равно None или не указано, используется контекст по умолчанию multiprocessing. См. Contexts and start methods.

initializer – это необязательный вызываемый объект, который вызывается в начале каждого рабочего процесса; initargs – это кортеж аргументов, передаваемых инициализатору. Если initializer вызывает исключение, все текущие ожидающие задания вызовут BrokenProcessPool, а также любая попытка отправить больше заданий в пул.

max_tasks_per_child – это необязательный аргумент, который указывает максимальное количество задач, которое может выполнить один процесс, прежде чем он завершится и будет заменен новым рабочим процессом. По умолчанию max_tasks_per_child равно None, что означает, что рабочие процессы будут жить до тех пор, пока существует пул. Когда задан максимум, по умолчанию будет использоваться метод запуска «spawn» в отсутствие параметра mp_context. Эта функция несовместима с методом запуска «fork».

Примечание

Были сообщения об ошибках при использовании функции max_tasks_per_child, которая может привести к зависанию ProcessPoolExecutor в некоторых обстоятельствах. Следите за ее разрешением в gh-115634.

Изменено в версии 3.3: Когда один из рабочих процессов завершается аварийно, теперь вызывается ошибка BrokenProcessPool. Ранее поведение было неопределенным, но операции с исполнителем или его future часто приводили к зависанию или взаимоблокировке.

Изменено в версии 3.7: Был добавлен аргумент mp_context, чтобы позволить пользователям управлять методом запуска рабочих процессов, созданных пулом.

Добавлены аргументы initializer и initargs.

Изменено в версии 3.11: Был добавлен аргумент max_tasks_per_child, чтобы позволить пользователям управлять временем жизни рабочих процессов в пуле.

Изменено в версии 3.12: В системах POSIX, если ваше приложение имеет несколько потоков и контекст multiprocessing использует метод запуска "fork": функция os.fork(), вызываемая внутри для порождения рабочих процессов, может вызвать DeprecationWarning. Передайте mp_context, настроенный на использование другого метода запуска. См. документацию os.fork() для дальнейших пояснений.

Изменено в версии 3.13: max_workers по умолчанию использует os.process_cpu_count() вместо os.cpu_count().

Изменено в версии 3.14: Метод запуска процесса по умолчанию (см. Contexts and start methods) изменился с fork. Если вам требуется метод запуска fork для ProcessPoolExecutor, вы должны явно передать mp_context=multiprocessing.get_context("fork").

terminate_workers()

Пытается немедленно завершить все живые рабочие процессы, вызывая Process.terminate для каждого из них. Внутренне также вызывает Executor.shutdown(), чтобы убедиться, что все другие ресурсы, связанные с исполнителем, освобождены.

После вызова этого метода вызывающая сторона больше не должна отправлять задачи исполнителю.

Добавлено в версии 3.14.

kill_workers()

Пытается убить все живые рабочие процессы немедленно, вызывая Process.kill для каждого из них. Внутренне также вызывает Executor.shutdown(), чтобы убедиться, что все другие ресурсы, связанные с исполнителем, освобождены.

После вызова этого метода вызывающая сторона больше не должна отправлять задачи исполнителю.

Добавлено в версии 3.14.

ProcessPoolExecutor ExampleПример ProcessPoolExecutor

python
import concurrent.futures
import math

PRIMES = [
    112272535095293,
    112582705942171,
    112272535095293,
    115280095190773,
    115797848077099,
    1099726899285419]

def is_prime(n):
    if n < 2:
        return False
    if n == 2:
        return True
    if n % 2 == 0:
        return False

    sqrt_n = int(math.floor(math.sqrt(n)))
    for i in range(3, sqrt_n + 1, 2):
        if n % i == 0:
            return False
    return True

def main():
    with concurrent.futures.ProcessPoolExecutor() as executor:
        for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):
            print('%d is prime: %s' % (number, prime))

if __name__ == '__main__':
    main()

Future ObjectsОбъекты Future

Класс Future инкапсулирует асинхронное выполнение вызываемого объекта. Экземпляры Future создаются с помощью Executor.submit().

class concurrent.futures.Future

Инкапсулирует асинхронное выполнение вызываемого объекта. Future экземпляры создаются с помощью Executor.submit() и не должны создаваться напрямую, за исключением тестирования.

cancel()

Пытается отменить вызов. Если вызов в данный момент выполняется или уже завершён и не может быть отменён, то метод вернёт False, в противном случае вызов будет отменён и метод вернёт True.

cancelled()

Возвращает True, если вызов был успешно отменён.

running()

Возвращает True, если вызов в данный момент выполняется и не может быть отменён.

done()

Возвращает True, если вызов был успешно отменён или завершён.

result(timeout=None)

Возвращает значение, возвращённое вызовом. Если вызов ещё не завершён, то этот метод будет ожидать до timeout секунд. Если вызов не завершится за timeout секунд, будет возбуждено исключение TimeoutError. timeout может быть целым числом или числом с плавающей запятой. Если timeout не указан или равен None, ограничения на время ожидания нет.

Если future был отменён до завершения, будет возбуждено исключение CancelledError.

Если вызов возбудил исключение, этот метод возбудит то же самое исключение.

exception(timeout=None)

Возвращает исключение, возбуждённое вызовом. Если вызов ещё не завершён, то этот метод будет ожидать до timeout секунд. Если вызов не завершится за timeout секунд, будет возбуждено исключение TimeoutError. timeout может быть целым числом или числом с плавающей запятой. Если timeout не указан или равен None, ограничения на время ожидания нет.

Если future был отменён до завершения, будет возбуждено исключение CancelledError.

Если вызов завершился без возбуждения исключения, возвращается None.

add_done_callback(fn)

Прикрепляет вызываемый объект fn к future. fn будет вызван, с future в качестве единственного аргумента, когда future будет отменён или завершит выполнение.

Добавленные вызываемые объекты вызываются в порядке их добавления и всегда вызываются в потоке, принадлежащем процессу, который их добавил. Если вызываемый объект возбуждает исключение, являющееся подклассом Exception, оно будет зарегистрировано и проигнорировано. Если вызываемый объект возбуждает исключение, являющееся подклассом BaseException, то поведение не определено.

Если future уже завершён или отменён, fn будет вызван немедленно.

Следующие методы Future предназначены для использования в модульных тестах и реализациях Executor.

set_running_or_notify_cancel()

Этот метод должен вызываться только реализациями Executor перед выполнением работы, связанной с Future, и модульными тестами.

Если метод возвращает False, то Future был отменён, т.е. Future.cancel() был вызван и вернул True. Все потоки, ожидающие завершения Future (т.е. через as_completed() или wait()), будут разбужены.

Если метод возвращает True, то Future не был отменён и переведён в состояние выполнения, т.е. вызовы Future.running() будут возвращать True.

Этот метод может быть вызван только один раз и не может быть вызван после Future.set_result() или Future.set_exception().

set_result(result)

Устанавливает результат работы, связанной с Future, в result.

Этот метод должен использоваться только реализациями Executor и модульными тестами.

Изменено в версии 3.8: Этот метод вызывает исключение concurrent.futures.InvalidStateError, если Future уже завершен.

set_exception(exception)

Устанавливает результат работы, связанной с Future, в Exception исключение.

Этот метод должен использоваться только реализациями Executor и модульными тестами.

Изменено в версии 3.8: Этот метод вызывает исключение concurrent.futures.InvalidStateError, если Future уже завершен.

Module FunctionsФункции модуля

concurrent.futures.wait(fs, timeout=None, return_when=ALL_COMPLETED)

Ожидает завершения экземпляров Future (возможно, созданных разными экземплярами Executor), заданных параметром fs. Дублирующиеся futures, переданные в fs, удаляются и будут возвращены только один раз. Возвращает именованный кортеж из двух множеств. Первое множество, названное done, содержит futures, которые завершились (завершенные или отмененные futures) до завершения ожидания. Второе множество, названное not_done, содержит futures, которые не завершились (ожидающие или выполняющиеся futures).

timeout можно использовать для управления максимальным количеством секунд ожидания перед возвратом. timeout может быть целым числом или числом с плавающей запятой. Если timeout не указан или равен None, время ожидания не ограничено.

return_when указывает, когда эта функция должна вернуть результат. Он должен быть одной из следующих констант:

Константа

Описание

concurrent.futures.FIRST_COMPLETED

Функция вернёт результат, когда любой future завершится или будет отменён.

concurrent.futures.FIRST_EXCEPTION

Функция вернёт результат, когда любой future завершится, вызвав исключение. Если ни один future не вызовет исключение, то это эквивалентно ALL_COMPLETED.

concurrent.futures.ALL_COMPLETED

Функция вернёт результат, когда все future завершатся или будут отменены.

concurrent.futures.as_completed(fs, timeout=None)

Возвращает итератор по экземплярам Future (возможно, созданных разными экземплярами Executor), заданным параметром fs, который выдает futures по мере их завершения (завершенные или отмененные futures). Любые futures, переданные в fs, которые дублируются, будут возвращены один раз. Futures, завершившиеся до вызова as_completed(), будут выданы первыми. Возвращаемый итератор вызывает исключение TimeoutError, если __next__() вызывается, а результат недоступен через timeout секунд после первоначального вызова as_completed(). timeout может быть целым числом или числом с плавающей запятой. Если timeout не указан или равен None, время ожидания не ограничено.

Смотрите также

PEP 3148 – futures - выполнение вычислений асинхронно

Предложение, которое описывало эту возможность для включения в стандартную библиотеку Python.

Exception classesКлассы исключений

exception concurrent.futures.CancelledError

Возбуждается, когда future отменен.

exception concurrent.futures.TimeoutError

Устаревший псевдоним TimeoutError, возбуждается, когда операция future превышает заданный тайм-аут.

Изменено в версии 3.11: Этот класс стал псевдонимом TimeoutError.

exception concurrent.futures.BrokenExecutor

Производный от RuntimeError, этот класс исключения возбуждается, когда исполнитель по какой-то причине сломан и не может использоваться для отправки или выполнения новых задач.

Добавлено в версии 3.7.

exception concurrent.futures.InvalidStateError

Возбуждается, когда над future выполняется операция, недопустимая в текущем состоянии.

Добавлено в версии 3.8.

exception concurrent.futures.thread.BrokenThreadPool

Производный от BrokenExecutor, этот класс исключения возбуждается, когда один из рабочих потоков ThreadPoolExecutor не смог инициализироваться.

Добавлено в версии 3.7.

exception concurrent.futures.interpreter.BrokenInterpreterPool

Производный от BrokenThreadPool, этот класс исключения возбуждается, когда один из рабочих потоков InterpreterPoolExecutor не смог инициализироваться.

Добавлено в версии 3.14.

exception concurrent.futures.process.BrokenProcessPool

Производный от BrokenExecutor (ранее RuntimeError), этот класс исключения возбуждается, когда один из рабочих процессов ProcessPoolExecutor завершился некорректным образом (например, если он был убит извне).

Добавлено в версии 3.3.