Документация Python неофициальный перевод

concurrent.futures.md

277 строк · 25.2 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.3/library/concurrent.futures.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 17.4. [`concurrent.futures`](https://python-all.ru/3.3/library/concurrent.futures.html#module-concurrent.futures) – Запуск параллельных задач89Новое в версии 3.2.1011**Исходный код:** [Lib/concurrent/futures/thread.py](https://python-all.ru/src/3.3/Lib/concurrent/futures/thread.py) и [Lib/concurrent/futures/process.py](https://python-all.ru/src/3.3/Lib/concurrent/futures/process.py)1213---1415Модуль [`concurrent.futures`](https://python-all.ru/3.3/library/concurrent.futures.html#module-concurrent.futures) предоставляет высокоуровневый интерфейс для асинхронного выполнения вызываемых объектов.1617Асинхронное выполнение может производиться с помощью потоков, используя [`ThreadPoolExecutor`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor), или отдельных процессов, используя [`ProcessPoolExecutor`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.ProcessPoolExecutor). Оба реализуют один и тот же интерфейс, который определён абстрактным классом [`исполнитель`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Executor).1819## 17.4.1. Объекты исполнителя2021#### `class concurrent.futures.Executor`2223Абстрактный класс, предоставляющий методы для асинхронного выполнения вызовов. Его не следует использовать напрямую, а через его конкретные подклассы.2425> #### `submit(fn, *args, **kwargs)`26>27> Планирует выполнение вызываемого объекта *fn* в виде `fn(*args **kwargs)` и возвращает объект [`Future`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Future), представляющий выполнение вызываемого объекта.28>29> ```python30> with ThreadPoolExecutor(max_workers=1) as executor:31>     future = executor.submit(pow, 323, 1235)32>     print(future.result())33> ```34>35> #### `map(func, *iterables, timeout=None)`36>37> Эквивалентно [`map(func, *iterables)`](https://python-all.ru/3.3/library/functions.html#map), за исключением того, что *func* выполняется асинхронно, и несколько вызовов *func* могут производиться одновременно. Возвращаемый итератор возбуждает исключение [`TimeoutError`](https://python-all.ru/3.3/library/exceptions.html#TimeoutError), если [`__next__()`](https://python-all.ru/3.3/library/stdtypes.html#iterator.__next__) вызывается, а результат недоступен через *timeout* секунд после исходного вызова [`Executor.map()`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Executor.map). *timeout* может быть int или float. Если *timeout* не указан или равен `None`, то время ожидания не ограничено. Если вызов возбуждает исключение, то это исключение будет возбуждено при получении его значения из итератора.38>39> #### `shutdown(wait=True)`40>41> Сообщает исполнителю, что он должен освободить все используемые ресурсы, когда завершится выполнение ожидающих future. Вызовы [`Executor.submit()`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Executor.submit) и [`Executor.map()`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Executor.map), сделанные после shutdown, возбудят [`RuntimeError`](https://python-all.ru/3.3/library/exceptions.html#RuntimeError).42>43> Если *wait* равен `True`, этот метод не вернёт управление, пока не завершится выполнение всех ожидающих future и не будут освобождены ресурсы, связанные с исполнителем. Если *wait* равен `False`, метод вернёт управление немедленно, а ресурсы, связанные с исполнителем, будут освобождены, когда завершится выполнение всех ожидающих future. Независимо от значения *wait*, вся программа Python не завершится, пока не закончится выполнение всех ожидающих future.44>45> Можно избежать явного вызова этого метода, используя оператор [`with`](https://python-all.ru/3.3/reference/compound_stmts.html#with), который завершит работу [`исполнителя`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Executor) (с ожиданием, как если бы [`Executor.shutdown()`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Executor.shutdown) был вызван с параметром *wait*, установленным в `True`):46>47> ```python48> import shutil49> with ThreadPoolExecutor(max_workers=4) as e:50>     e.submit(shutil.copy, 'src1.txt', 'dest1.txt')51>     e.submit(shutil.copy, 'src2.txt', 'dest2.txt')52>     e.submit(shutil.copy, 'src3.txt', 'dest3.txt')53>     e.submit(shutil.copy, 'src3.txt', 'dest4.txt')54> ```5556## 17.4.2. ThreadPoolExecutor5758[`ThreadPoolExecutor`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor) – это подкласс [`Executor`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Executor), использующий пул потоков для асинхронного выполнения вызовов.5960Взаимные блокировки могут возникать, когда вызываемый объект, связанный с [`Future`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Future), ожидает результаты другого [`Future`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Future). Например:6162```python63import time64def wait_on_b():65    time.sleep(5)66    print(b.result()) # b никогда не завершится, потому что он ожидает a.67    return 56869def wait_on_a():70    time.sleep(5)71    print(a.result()) # a никогда не завершится, потому что он ожидает b.72    return 67374executor = ThreadPoolExecutor(max_workers=2)75a = executor.submit(wait_on_b)76b = executor.submit(wait_on_a)77```7879И:8081```python82def wait_on_future():83    f = executor.submit(pow, 5, 2)84    # Это никогда не завершится, потому что есть только один рабочий поток и85    # он выполняет эту функцию.86    print(f.result())8788executor = ThreadPoolExecutor(max_workers=1)89executor.submit(wait_on_future)90```9192#### `class concurrent.futures.ThreadPoolExecutor(max_workers)`9394Подкласс [`исполнителя`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Executor), который использует пул из не более чем *max\_workers* потоков для асинхронного выполнения вызовов.9596### 17.4.2.1. Пример ThreadPoolExecutor9798```python99import concurrent.futures100import urllib.request101102URLS = ['http://www.foxnews.com/',103        'http://www.cnn.com/',104        'http://europe.wsj.com/',105        'http://www.bbc.co.uk/',106        'http://some-made-up-domain.com/']107108# Извлечь одну страницу и вывести URL и содержимое109def load_url(url, timeout):110    conn = urllib.request.urlopen(url, timeout=timeout)111    return conn.readall()112113# Можно использовать инструкцию with, чтобы гарантировать своевременную очистку потоков114with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:115    # Запустить операции загрузки и пометить каждый future его URL116    future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}117    for future in concurrent.futures.as_completed(future_to_url):118        url = future_to_url[future]119        try:120            data = future.result()121        except Exception as exc:122            print('%r generated an exception: %s' % (url, exc))123        else:124            print('%r page is %d bytes' % (url, len(data)))125```126127## 17.4.3. ProcessPoolExecutor128129Класс [`ProcessPoolExecutor`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.ProcessPoolExecutor) – это подкласс [`исполнителя`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Executor), который использует пул процессов для асинхронного выполнения вызовов. [`ProcessPoolExecutor`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.ProcessPoolExecutor) использует модуль [`multiprocessing`](https://python-all.ru/3.3/library/multiprocessing.html#module-multiprocessing), что позволяет обойти [*глобальную блокировку интерпретатора*](https://python-all.ru/3.3/glossary.html#term-global-interpreter-lock), но также означает, что выполняться и возвращаться могут только сериализуемые объекты.130131Вызов методов [`исполнителя`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Executor) или [`Future`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Future) из вызываемого объекта, переданного в [`ProcessPoolExecutor`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.ProcessPoolExecutor), приведёт к взаимной блокировке.132133#### `class concurrent.futures.ProcessPoolExecutor(max_workers=None)`134135Подкласс [`исполнителя`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Executor), который выполняет вызовы асинхронно, используя пул из не более чем *max\_workers* процессов. Если *max\_workers* равен `None` или не указан, по умолчанию будет использовано количество процессоров на машине.136137Изменено в версии 3.3: Когда один из рабочих процессов завершается аварийно, теперь возникает ошибка [`BrokenProcessPool`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.BrokenProcessPool). Ранее поведение было неопределённым, но операции над исполнителем или его future'ами часто приводили к зависанию или взаимоблокировке.138139### 17.4.3.1. Пример ProcessPoolExecutor140141```python142import concurrent.futures143import math144145PRIMES = [146    112272535095293,147    112582705942171,148    112272535095293,149    115280095190773,150    115797848077099,151    1099726899285419]152153def is_prime(n):154    if n % 2 == 0:155        return False156157    sqrt_n = int(math.floor(math.sqrt(n)))158    for i in range(3, sqrt_n + 1, 2):159        if n % i == 0:160            return False161    return True162163def main():164    with concurrent.futures.ProcessPoolExecutor() as executor:165        for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):166            print('%d is prime: %s' % (number, prime))167168if __name__ == '__main__':169    main()170```171172## 17.4.4. Объекты Future173174Класс [`Future`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Future) инкапсулирует асинхронное выполнение вызываемого объекта. Экземпляры [`Future`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Future) создаются с помощью [`Executor.submit()`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Executor.submit).175176#### `class concurrent.futures.Future`177178Инкапсулирует асинхронное выполнение вызываемого объекта. Экземпляры [`Future`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Future) создаются с помощью [`Executor.submit()`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Executor.submit) и не должны создаваться напрямую, за исключением тестирования.179180> #### `cancel()`181>182> Пытается отменить вызов. Если вызов в данный момент выполняется и не может быть отменён, метод вернёт `False`; в противном случае вызов будет отменён, и метод вернёт `True`.183>184> #### `cancelled()`185>186> Возвращает `True`, если вызов был успешно отменён.187>188> #### `running()`189>190> Возвращает `True`, если вызов в данный момент выполняется и не может быть отменён.191>192> #### `done()`193>194> Возвращает `True`, если вызов был успешно отменён или завершил выполнение.195>196> #### `result(timeout=None)`197>198> Возвращает значение, возвращённое вызовом. Если вызов ещё не завершён, то этот метод будет ожидать до *timeout* секунд. Если вызов не завершится за *timeout* секунд, то будет вызвано [`TimeoutError`](https://python-all.ru/3.3/library/exceptions.html#TimeoutError). *timeout* может быть int или float. Если *timeout* не указан или равен `None`, то время ожидания не ограничено.199>200> Если future будет отменён до завершения, то возникнет `CancelledError`.201>202> Если вызов вызвал исключение, этот метод возбудит то же самое исключение.203>204> #### `exception(timeout=None)`205>206> Возвращает исключение, вызванное вызовом. Если вызов ещё не завершён, то этот метод будет ожидать до *timeout* секунд. Если вызов не завершится за *timeout* секунд, то будет вызвано [`TimeoutError`](https://python-all.ru/3.3/library/exceptions.html#TimeoutError). *timeout* может быть int или float. Если *timeout* не указан или равен `None`, то время ожидания не ограничено.207>208> Если future будет отменён до завершения, то возникнет `CancelledError`.209>210> Если вызов завершился без исключения, возвращается `None`.211>212> #### `add_done_callback(fn)`213>214> Прикрепляет вызываемый объект *fn* к future. *fn* будет вызван с future в качестве единственного аргумента, когда future отменён или завершит выполнение.215>216> Добавленные вызываемые объекты вызываются в порядке их добавления и всегда вызываются в потоке, принадлежащем процессу, который их добавил. Если вызываемый объект порождает подкласс [`Exception`](https://python-all.ru/3.3/library/exceptions.html#Exception), это исключение регистрируется и игнорируется. Если вызываемый объект порождает подкласс [`BaseException`](https://python-all.ru/3.3/library/exceptions.html#BaseException), поведение не определено.217>218> Если future уже завершён или отменён, *fn* будет вызван немедленно.219220Следующие методы [`Future`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Future) предназначены для использования в модульных тестах и реализациях [`Executor`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Executor).221222> #### `set_running_or_notify_cancel()`223>224> Этот метод должен вызываться только реализациями [`Executor`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Executor) перед выполнением работы, связанной с [`Future`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Future), и модульными тестами.225>226> Если метод возвращает `False`, то [`Future`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Future) был отменён, т.е. [`Future.cancel()`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Future.cancel) был вызван и вернул *True*. Все потоки, ожидающие завершения [`Future`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Future) (например, через [`as_completed()`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.as_completed) или [`wait()`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.wait)), будут разбужены.227>228> Если метод возвращает `True`, то [`Future`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Future) не был отменён и переведён в состояние выполнения, т.е. вызовы [`Future.running()`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Future.running) будут возвращать *True*.229>230> Этот метод можно вызвать только один раз, и его нельзя вызывать после вызова [`Future.set_result()`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Future.set_result) или [`Future.set_exception()`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Future.set_exception).231>232> #### `set_result(result)`233>234> Устанавливает результат работы, связанной с [`Future`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Future), в *result*.235>236> Этот метод должен использоваться только реализациями [`Executor`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Executor) и модульными тестами.237>238> #### `set_exception(exception)`239>240> Устанавливает результат работы, связанной с [`Future`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Future), в [`Exception`](https://python-all.ru/3.3/library/exceptions.html#Exception) *исключение*.241>242> Этот метод должен использоваться только реализациями [`Executor`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Executor) и модульными тестами.243244## 17.4.5. Функции модуля245246#### `concurrent.futures.wait(fs, timeout=None, return_when=ALL_COMPLETED)`247248Ожидает завершения экземпляров [`Future`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Future) (возможно, созданных разными экземплярами [`Executor`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Executor)), переданных в *fs*. Возвращает именованный кортеж из двух множеств. Первое множество с именем `done` содержит future, которые завершились (успешно или отменой) до окончания ожидания. Второе множество с именем `not_done` содержит незавершённые future.249250*timeout* можно использовать для задания максимального времени ожидания в секундах перед возвратом. *timeout* может быть целым числом (int) или числом с плавающей точкой (float). Если *timeout* не указан или равен `None`, время ожидания не ограничено.251252*return\_when* указывает, когда эта функция должна вернуть результат. Он должен быть одной из следующих констант:253254| Константа | Описание |255| --- | --- |256| `FIRST_COMPLETED` | Функция вернёт результат, когда любой future завершится или будет отменён. |257| `FIRST_EXCEPTION` | Функция вернёт результат, когда любой future завершится возбуждением исключения. Если ни один future не возбудит исключение, это эквивалентно `ALL_COMPLETED`. |258| `ALL_COMPLETED` | Функция вернёт результат, когда все future завершатся или будут отменены. |259260#### `concurrent.futures.as_completed(fs, timeout=None)`261262Возвращает итератор по экземплярам [`Future`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Future) (возможно, созданным разными экземплярами [`Executor`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.Executor)), переданным в *fs*, который возвращает future по мере их завершения (успешно или отменой). Любые future, переданные в *fs*, которые дублируются, будут возвращены один раз. Любые future, завершившиеся до вызова [`as_completed()`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.as_completed), будут возвращены первыми. Возвращаемый итератор возбуждает [`TimeoutError`](https://python-all.ru/3.3/library/exceptions.html#TimeoutError), если вызван [`__next__()`](https://python-all.ru/3.3/library/stdtypes.html#iterator.__next__), а результат недоступен по прошествии *timeout* секунд с момента исходного вызова [`as_completed()`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.as_completed). *timeout* может быть int или float. Если *timeout* не указан или равен `None`, то время ожидания не ограничено.263264> **См. также**265>266> **[**PEP 3148**](https://python-all.ru/3.3/library/concurrent.futures.html) – futures - execute computations asynchronously**267>268> Предложение, которое описывало эту возможность для включения в стандартную библиотеку Python.269270## 17.4.6. Классы исключений271272#### `exception concurrent.futures.BrokenProcessPool`273274Производный от [`RuntimeError`](https://python-all.ru/3.3/library/exceptions.html#RuntimeError), этот класс исключения возникает, когда один из рабочих процессов [`ProcessPoolExecutor`](https://python-all.ru/3.3/library/concurrent.futures.html#concurrent.futures.ProcessPoolExecutor) завершается некорректно (например, если он был принудительно завершён извне).275276Новое в версии 3.3.277