Python

concurrent.futures — 병렬 작업 실행하기

Added in version 3.2.

소스 코드: Lib/concurrent/futures/thread.py, Lib/concurrent/futures/process.py, 및 Lib/concurrent/futures/interpreter.py


concurrent.futures 모듈은 콜러블을 비동기적으로 실행하기 위한 고수준 인터페이스를 제공합니다.

비동기 실행은 ThreadPoolExecutor 또는 InterpreterPoolExecutor`를 사용하여 스레드를 통해, 또는 :class:`ProcessPoolExecutor`를 사용하여 별도의 프로세스를 통해 수행할 있습니다. 각각은 추상적인 :class:`Executor 클래스에 의해 정의된 동일한 인터페이스를 구현합니다.

concurrent.futures.Future`는 :mod:`asyncio 태스크 및 코루틴 사용을 위해 설계된 asyncio.Future`와 혼동해서는 됩니다. 객체에 대한 자세한 비교는 :doc:`asyncio's Future 문서를 참조하십시오.

가용성: not WASI.

이 모듈은 웹어셈블리에서 작동하지 않거나 제공되지 않습니다. 자세한 내용은 웹어셈블리 플랫폼을 참조하세요.

Executor 객체

class concurrent.futures.Executor

비동기적으로 호출을 실행하는 메서드를 제공하는 추상 클래스입니다. 직접 사용해서는 안 되며, 구체적인 하위 클래스를 통해 사용해야 합니다.

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

콜러블 fnfn(*args, **kwargs) 처럼 실행되도록 예약하고, 콜러블 객체의 실행을 나타내는 Future 객체를 반환합니다.

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 에 대한 여러 호출이 동시에 이루어질 수 있습니다.

반환된 이터레이터는 __next__() 가 호출되었을 때, Executor.map() 에 대한 최초 호출에서 timeout 초 후에도 결과를 사용할 수 없는 경우 TimeoutError 를 발생시킵니다. timeout 은 int 또는 float가 될 수 있습니다. timeout 이 지정되지 않았거나 None 인 경우, 대기 시간에는 제한이 없습니다.

fn 호출이 예외를 일으키면, 값을 이터레이터에서 꺼낼 때 해당 예외가 발생합니다.

ProcessPoolExecutor 를 사용하는 경우, 이 메서드는 iterables 를 여러 묶음으로 잘라서 별도의 작업으로 풀에 제출합니다. 이러한 묶음의 (대략적인) 크기는 chunksize 를 양의 정수로 설정하여 지정할 수 있습니다. 매우 긴 iterables의 경우, chunksize 에 큰 값을 사용하는 것이 기본 크기 1에 비해 성능을 크게 향상시킬 수 있습니다. ThreadPoolExecutorInterpreterPoolExecutor 에서는 chunksize 가 영향을 주지 않습니다.

버전 3.5에서 변경: chunksize 매개 변수가 추가되었습니다.

버전 3.14에서 변경: buffersize 매개 변수가 추가되었습니다.

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

현재 계류 중인 퓨처가 실행 완료될 때, 사용 중인 모든 자원을 해제해야 한다는 것을 실행기에 알립니다. 종료(shutdown) 후에 이루어지는 Executor.submit()Executor.map() 호출은 RuntimeError 를 발생시킵니다.

waitTrue 면, 계류 중인 모든 퓨처가 실행을 마치고 실행기와 관련된 자원이 해제될 때까지 이 메서드는 돌아오지 않습니다. waitFalse 면, 이 메서드는 즉시 돌아오고 실행기와 연관된 자원은 계류 중인 모든 퓨처가 실행을 마칠 때 해제됩니다. wait 의 값과 관계없이, 모든 계류 중인 퓨처가 실행을 마칠 때까지 전체 파이썬 프로그램이 종료되지 않습니다.

cancel_futuresTrue이면, 이 메서드는 실행기가 실행을 시작시키지 않은 계류 중인 모든 퓨처를 취소합니다. cancel_futures의 값과 관계없이 완료되었거나 실행 중인 퓨처는 취소되지 않습니다.

cancel_futureswait가 모두 True이면, 이 메서드가 반환하기 전에 실행기가 실행을 시작한 모든 퓨처가 완료됩니다. 나머지 퓨처는 취소됩니다.

이 메서드를 명시적으로 호출할 필요가 없도록 하려면, 스레터를 context managerwith 문을 통해 사용하면 됩니다. 이렇게 하면 Executor 가 종료됩니다 (이때 Executor.shutdown()waitTrue 로 설정된 것처럼 대기합니다):

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 의 결과를 기다릴 때 교착 상태가 발생할 수 있습니다. 예를 들면:

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)

그리고:

def wait_on_future():
    f = executor.submit(pow, 5, 2)
    # 작업자 스레드가 하나뿐인데, wait_on_future 를 실행하고 있으므로
    # f 는 완료되지 않습니다.
    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=())

최대 max_workers 스레드의 풀을 사용하여 호출을 비동기적으로 실행하는 Executor 서브 클래스.

ThreadPoolExecutor 에 들어간 모든 스레드는 인터프리터가 종료되기 전에 연결(joined)됩니다. 참고로, 이를 실행하는 종료 핸들러는 atexit 을 사용하여 추가된 어떤 종료 핸들러보다 먼저 실행됩니다. 이는 메인 스레드의 예외는 스레드에 정상적으로 종료를 신호 보내기 위해 포착되고 처리되어야 함을 의미합니다. 이러한 이유로, ThreadPoolExecutor 를 장시간 실행되는 작업에 사용하지 않는 것이 좋습니다.

initializer 는 각 작업자 스레드의 시작 부분에서 호출되는 선택적 콜러블입니다; initargs 는 initializer에 전달되는 인자들의 튜플입니다. initializer 가 예외를 발생시키는 경우, 현재 계류 중인 모든 작업과 풀에 추가로 작업을 제출하려는 시도는 BrokenThreadPool 을 발생시킵니다.

버전 3.5에서 변경: max_workersNone 이거나 주어지지 않았다면, 기본값으로 기계의 프로세서 수에 5 를 곱한 값을 사용합니다. ThreadPoolExecutor 가 CPU 작업보다는 I/O를 동시에 진행하는데 자주 쓰이고, 작업자의 수가 ProcessPoolExecutor 보다 많아야 한다고 가정하고 있습니다.

버전 3.6에서 변경: 디버깅 편의를 위해 사용자가 풀이 만드는 작업자 스레드의 threading.Thread 이름을 제어 할 수 있도록, thread_name_prefix 매개 변수를 추가했습니다.

버전 3.7에서 변경: initializerinitargs 인자가 추가되었습니다.

버전 3.8에서 변경: max_workers의 기본값은 min(32, os.cpu_count() + 4)로 변경됩니다. 이 기본값은 I/O 병목 작업을 위해 최소 5개의 작업자를 유지합니다. GIL을 반납하는 CPU 병목 작업을 위해 최대 32개의 CPU 코어를 사용합니다. 또한 많은 코어를 가진 시스템에서 매우 큰 자원을 묵시적으로 사용하는 것을 방지합니다.

ThreadPoolExecutor는 이제 max_workers 작업자 스레드를 시작하기 전에 유휴 작업자 스레드를 재사용합니다.

버전 3.13에서 변경: max_workers 의 기본값이 min(32, (os.process_cpu_count() or 1) + 4) \로 변경되었습니다.

ThreadPoolExecutor 예제

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:
    # 로드 작업을 시작하고 각 퓨처의 해당 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

Added in version 3.14.

InterpreterPoolExecutor 클래스는 풀의 인터프리터들을 사용하여 호출을 비동기적으로 실행합니다. 이는 :class:`ThreadPoolExecutor`의 하위 클래스이며, 이는 각 작업자가 자체 스레드 내에서 실행됨을 의미합니다. 여기서 차이점은 각 작업자가 자체 인터프리터를 가지며, 해당 인터프리터를 사용하여 각 작업을 실행한다는 점입니다.

인터프리터만을 사용하는 것보다 인터프리터를 사용하는 가장 큰 이점은 진정한 멀티 코어 병렬성입니다. 각 인터프리터는 자체 :term:`Global Interpreter Lock <global interpreter lock>`를 가지고 있으므로, 한 인터프리터에서 실행되는 코드는 한 CPU 코어에서 실행될 수 있고, 다른 인터프리터의 코드는 다른 코어에서 막힘없이 실행될 수 있습니다.

다중 인터프리터와 함께 사용하기 위한 동시 코드를 작성하는 것은 추가적인 노력이 필요할 수 있습니다. 하지만, 이는 인터프리터가 어떻게 그리고 언제 상호 작용해야 하는지에 대해 신중하게 접근하고, 인터프리터 간에 어떤 데이터를 공유하는지 명시적으로 지정하도록 강요하기 때문에 발생합니다. 이로 인해 진정한 멀티 코어 병렬 처리*를 포함하여 여러 가지 이점을 통해 추가적인 노력을 균형 있게 맞출 수 있습니다. 예를 들어, 이렇게 작성된 코드는 동시성을 이해하기 더 쉽게 만들어줍니다. 또 다른 주요 이점은 경쟁 조건과 같은 스레드 사용의 여러 큰 문제 지점들을 다룰 필요가 없다는 것입니다.

각 워커의 인터프리터는 다른 모든 인터프리터로부터 격리됩니다. “격리(Isolated)”란 각 인터프리터가 자체 런타임 상태를 가지고 완전히 독립적으로 작동한다는 것을 의미합니다. 예를 들어, 한 인터프리터에서 sys.stdout 을 리디렉션하더라도 다른 인터프리터로 자동으로 리디렉션되지 않습니다. 한 인터프리터에서 모듈을 임포트하더라도 다른 인터프리터에서는 자동으로 임포트되지 않습니다. 필요한 인터프리터에서 해당 모듈을 별도로 임포트해야 합니다. 실제로, 인터프리터에 임포트된 각 모듈은 sys, builtins, 그리고 심지어 __main__ 에 있는 다른 인터프리터의 동일 모듈과도 완전히 분리된 객체입니다.

격리(Isolation)는 가변 객체나 다른 데이터가 동시에 여러 인터프리터에 의해 사용될 수 없다는 것을 의미합니다. 이는 사실상 인터프리터가 그러한 객체나 데이터를 실제로 공유할 수 없다는 것을 의미합니다. 대신, 각 인터프리터는 자체 복사본을 가지고 있어야 하며, 복사본 간의 모든 변경 사항은 수동으로 동기화해야 합니다. 같은 내장 싱글톤(builtin singletons), 문자열, 그리고 불변 객체의 튜플과 같은 불변 객체와 데이터는 이러한 제한이 없습니다.

인터프리터 간의 통신 및 동기화는 PEP 734 에 제안된 것과 같은 전용 도구를 사용하는 것이 가장 효과적입니다. 덜 효율적인 대안은 pickle 로 직렬화한 다음 바이트를 공유 socket 또는 pipe 를 통해 전송하는 것입니다.

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

최대 max_workers 개의 스레드 풀을 사용하여 호출을 비동기적으로 실행하는 ThreadPoolExecutor 서브 클래스입니다. 각 스레드는 자체 인터프리터에서 작업을 실행합니다. 워커 인터프리터들은 서로 격리되어 있어, 각각 자체 런타임 상태를 가지고 있으며, 모든 가변 객체나 기타 데이터를 공유할 수 없습니다. 각 인터프리터는 자체 :term:`Global Interpreter Lock <global interpreter lock>`을 가지므로, 이 실행기를 사용하여 실행된 코드는 진정한 멀티 코어 병렬 처리를 갖습니다.

선택적 initializerinitargs 인자는 ThreadPoolExecutor 의 것과 동일한 의미를 가집니다. 즉, 초기화 프로그램(initializer)은 각 워커가 생성될 때 실행되지만, 이 경우 워커의 인터프리터 내에서 실행됩니다. 실행기는 워커의 인터프리터로 전송할 때 initializerinitargspickle 을 사용하여 직렬화합니다.

참고

실행기는 initializer 로부터 발생하는 포착되지 않은 예외를 ExecutionFailed 로 대체할 수 있습니다.

상위 :class:`ThreadPoolExecutor`로부터의 다른 주의 사항들이 여기에 적용됩니다.

:meth:`~Executor.submit`과 :meth:`~Executor.map`은 정상적으로 작동하지만, 워커는 호출 가능 객체와 인자를 :mod:`pickle`을 사용하여 직렬화한 후 자신의 인터프리터로 전송합니다. 워커는 마찬가지로 반환되는 값도 직렬화하여 전송합니다.

워커의 현재 작업이 포착되지 않은 예외를 발생시키면, 워커는 항상 예외를 있는 그대로 보존하려고 시도합니다. 이것이 성공하면, 또한 원본 예외의 요약을 담고 있는 해당 ExecutionFailed 인스턴스로 __cause__ 를 설정합니다. 워커가 원본을 있는 그대로 보존할 수 없는 드문 경우라면, 대신 해당 ExecutionFailed 인스턴스를 직접 보존합니다.

ProcessPoolExecutor

ProcessPoolExecutor 클래스는 프로세스 풀을 사용하여 호출을 비동기적으로 실행하는 Executor 서브 클래스입니다. ProcessPoolExecutormultiprocessing 모듈을 사용합니다. 전역 인터프리터 록 을 피할 수 있도록 하지만, 오직 피클 가능한 객체만 실행되고 반환될 수 있음을 의미합니다.

__main__ 모듈은 작업자 서브 프로세스가 임포트 할 수 있어야 합니다. 즉, ProcessPoolExecutor 는 대화형 인터프리터에서 작동하지 않습니다.

ProcessPoolExecutor 에 제출된 콜러블에서 ExecutorFuture 메서드를 호출하면 교착 상태가 발생합니다.

:class:`multiprocessing.Process`에 따라 기능과 인자가 picklable(직렬화 가능한)해야 하는 제한 사항은 :meth:`~Executor.submit`과 :meth:`~Executor.map`을 :class:`ProcessPoolExecutor`에 사용할 때 적용됩니다. REPL이나 람다에서 정의된 함수는 작동한다고 기대해서는 안 됩니다.

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

최대 max_workers 프로세스의 풀을 사용하여 호출을 비동기적으로 실행하는 Executor 서브 클래스. max_workersNone 이거나 주어지지 않았다면, os.process_cpu_count()를 기본값으로 사용합니다. max_workers0 보다 작거나 같으면 ValueError 가 발생합니다. 윈도우에서, max_workers61보다 작거나 같아야 합니다. 그렇지 않으면 ValueError가 발생합니다. max_workersNone 이면, 더 많은 프로세서를 사용할 수 있다 할지라도 선택된 기본값은 최대 61이 될 것입니다. mp_contextmultiprocessing 컨텍스트이거나 None일 수 있습니다. 작업자들을 만드는데 사용될 것입니다. mp_contextNone 이거나 주어지지 않으면 기본 multiprocessing 컨텍스트가 사용됩니다. 컨텍스트 및 시작 방법을 참조하세요.

initializer 는 각 작업자 프로세스의 시작 부분에서 호출되는 선택적 콜러블입니다; initargs 는 initializer에 전달되는 인자들의 튜플입니다. initializer 가 예외를 발생시키는 경우, 현재 계류 중인 모든 작업과 풀에 추가로 작업을 제출하려는 시도는 BrokenProcessPool 을 발생시킵니다.

max_tasks_per_child 는, 단일 프로세스가 종료되고 새로운 작업 프로세스로 교체되기 전에 실행할 수 있는 최대 작업 수를 지정하는 선택적 인자입니다. 기본 max_tasks_per_childNone 이므로, 작업자 프로세스는 풀이 존재하는 한 계속 유지됩니다. 최대값이 지정되면, mp_context 매개변수가 없는 경우 기본적으로 “spawn” 멀티프로세싱 시작 방법이 사용됩니다. 이 기능은 “fork” 시작 방법과 호환되지 않습니다.

참고

max_tasks_per_child 기능을 사용할 때 버그가 보고되었으며, 이는 특정 상황에서 :class:`ProcessPoolExecutor`가 멈출 수 있습니다. 최종 해결책은 :gh:`115634`를 참조하십시오.

버전 3.3에서 변경: 작업자 프로세스 중 하나가 갑자기 종료되면, BrokenProcessPool 오류가 발생합니다. 이전에는, 동작이 정의되지 않았지만, 실행기나 그 퓨처에 대한 연산이 종종 멈추거나 교착 상태에 빠졌습니다.

버전 3.7에서 변경: mp_context 인자가 추가되어 사용자가 풀에서 만드는 작업자 프로세스의 시작 방법을 제어 할 수 있습니다.

initializerinitargs 인자가 추가되었습니다.

버전 3.11에서 변경: max_tasks_per_child 인자가 추가되어 사용자가 풀에 있는 작업자의 수명을 제어 할 수 있습니다.

버전 3.12에서 변경: POSIX 시스템에서 애플리케이션이 여러 스레드를 가지고 있고 multiprocessing 컨텍스트가 "fork" 시작 방법을 사용하는 경우: 워커를 생성하기 위해 내부적으로 호출되는 os.fork() 함수는 DeprecationWarning`을 발생시킬 있습니다. 다른 시작 방법을 사용하도록 구성된 *mp_context*를 전달하십시오. 자세한 설명은 :func:`os.fork 문서를 참조하십시오.

버전 3.13에서 변경: max_workers 는 기본적으로 os.process_cpu_count() 를 사용하며, os.cpu_count() 대신 사용합니다.

버전 3.14에서 변경: 기본 프로세스 시작 방법(참고: 컨텍스트 및 시작 방법)은 fork 에서 변경되었습니다. ProcessPoolExecutorfork 시작 방법이 필요한 경우, 반드시 mp_context=multiprocessing.get_context("fork") 를 명시적으로 전달해야 합니다.

terminate_workers()

각각의 살아있는 작업자 프로세스를 Process.terminate 메서드를 호출하여 즉시 종료하려고 시도합니다. 내부적으로는 또한 모든 관련 리소스가 해제되도록 :meth:`Executor.shutdown`을 호출합니다.

이 메서드를 호출한 후에는 호출자가 실행기에 작업을 제출해서는 안 됩니다.

Added in version 3.14.

kill_workers()

각각의 살아있는 작업자 프로세스를 Process.kill 메서드를 호출하여 즉시 종료하려고 시도합니다. 내부적으로는 또한 모든 관련 리소스가 해제되도록 :meth:`Executor.shutdown`을 호출합니다.

이 메서드를 호출한 후에는 호출자가 실행기에 작업을 제출해서는 안 됩니다.

Added in version 3.14.

ProcessPoolExecutor 예제

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 객체

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 은 int 또는 float가 될 수 있습니다. timeout 이 지정되지 않았거나 None 인 경우, 대기 시간에는 제한이 없습니다.

완료하기 전에 퓨처가 취소되면 CancelledError 가 발생합니다.

호출이 예외를 일으키는 경우, 이 메서드는 같은 예외를 발생시킵니다.

exception(timeout=None)

호출이 일으킨 예외를 돌려줍니다. 호출이 아직 완료되지 않는 경우, 이 메서드는 timeout 초까지 대기합니다. timeout 초 내에 호출이 완료되지 않으면 TimeoutError 가 발생합니다. timeout 은 int 또는 float가 될 수 있습니다. timeout 이 지정되지 않았거나 None 인 경우, 대기 시간에는 제한이 없습니다.

완료하기 전에 퓨처가 취소되면 CancelledError 가 발생합니다.

호출이 예외 없이 완료되면, None 이 반환됩니다.

add_done_callback(fn)

콜러블 fn 을 퓨처에 연결합니다. fn 은 퓨처가 취소되거나 실행이 종료될 때 퓨처를 유일한 인자로 호출됩니다.

추가된 콜러블은 추가된 순서대로 호출되며, 항상 콜러블을 추가한 프로세스에 속하는 스레드에서 호출됩니다. 콜러블이 Exception 서브 클래스를 발생시키면, 로그 되고 무시됩니다. 콜러블이 BaseException 서브 클래스를 발생시키면, 동작은 정의되지 않습니다.

퓨처가 이미 완료되었거나 취소된 경우 fn 이 즉시 호출됩니다.

다음 Future 메서드는 단위 테스트와 Executor 의 구현을 위한 것입니다.

set_running_or_notify_cancel()

이 메서드는 Future와 관련된 작업을 실행하기 전에 Executor 구현에 의해서만 호출되거나 단위 테스트에서만 호출되어야 합니다.

메서드가 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에서 변경: 이 메서드는 Future가 이미 완료되었으면 concurrent.futures.InvalidStateError를 발생시킵니다.

set_exception(exception)

Future와 관련된 작업 결과를 Exception exception 으로 설정합니다.

이 메서드는 Executor 구현과 단위 테스트에서만 사용해야 합니다.

버전 3.8에서 변경: 이 메서드는 Future가 이미 완료되었으면 concurrent.futures.InvalidStateError를 발생시킵니다.

모듈 함수

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

fs 로 주어진 여러 (서로 다른 Executor 인스턴스가 만든 것들도 가능합니다) Future 인스턴스들이 완료할 때까지 기다립니다. fs 로 주어진 중복 퓨처는 제거되고 한 번만 반환됩니다. 집합들의 이름있는 2-튜플을 돌려줍니다. done 이라는 이름의 첫 번째 집합은 대기가 끝나기 전에 완료된 (끝났거나 취소된) 퓨처를 담고 있습니다. not_done 이라는 이름의 두 번째 집합은 완료되지 않은 (계류 중이거나 실행 중인) 퓨처를 담고 있습니다.

timeout 은 반환하기 전에 대기 할 최대 시간(초)을 제어하는 데 사용할 수 있습니다. timeout 은 int 또는 float가 될 수 있습니다. timeout 이 지정되지 않았거나 None 인 경우, 대기 시간에는 제한이 없습니다.

return_when 은, 이 함수가 언제 반환되어야 하는지를 나타냅니다. 다음 상수 중 하나여야 합니다:

상수

설명

concurrent.futures.FIRST_COMPLETED

퓨처가 어느 하나라도 끝나거나 취소될 때 함수가 반환됩니다.

concurrent.futures.FIRST_EXCEPTION

어느 한 퓨처가 예외를 일으켜 완료하면 함수가 반환됩니다. 어떤 퓨처도 예외를 발생시키지 않으면 ALL_COMPLETED와 같습니다.

concurrent.futures.ALL_COMPLETED

모든 퓨처가 끝나거나 취소되면 함수가 반환됩니다.

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

fs 로 주어진 여러 (서로 다른 Executor 인스턴스가 만든 것들도 가능합니다) 퓨처들이 완료되는 대로 (끝났거나 취소된 퓨처) 일드 하는 Future 인스턴스의 이터레이터를 반환합니다. fs 에 중복된 퓨처가 들어있으면 한 번만 반환됩니다. as_completed() 가 호출되기 전에 완료한 모든 퓨처들이 먼저 일드 됩니다. 반환된 이터레이터는, __next__() 가 호출되고, as_completed() 호출 시점으로부터 timeout 초 후에 결과를 얻을 수 없는 경우 TimeoutError 를 발생시킵니다. timeout 은 int 또는 float가 될 수 있습니다. timeout 이 지정되지 않았거나 None 인 경우, 대기 시간에는 제한이 없습니다.

더 보기

PEP 3148 – 퓨처 - 계산을 비동기적으로 실행

파이썬 표준 라이브러리에 포함하기 위해, 이 기능을 설명한 제안.

예외 클래스

exception concurrent.futures.CancelledError

퓨처가 취소될 때 발생합니다.

exception concurrent.futures.TimeoutError

TimeoutError의 폐지된 별칭, 퓨처 연산이 지정된 시간제한을 초과할 때 발생합니다.

버전 3.11에서 변경: 이 클래스는 :exc:`TimeoutError`의 별칭으로 만들어졌습니다.

exception concurrent.futures.BrokenExecutor

RuntimeError 에서 파생됩니다, 이 예외 클래스는 어떤 이유로 실행기가 망가져서 새 작업을 제출하거나 실행할 수 없을 때 발생합니다.

Added in version 3.7.

exception concurrent.futures.InvalidStateError

퓨처에 현재 상태에서 허용되지 않는 연산이 수행될 때 발생합니다.

Added in version 3.8.

exception concurrent.futures.thread.BrokenThreadPool

BrokenExecutor 에서 파생됩니다, 이 예외 클래스는 ThreadPoolExecutor 의 작업자 중 하나가 초기화에 실패했을 때 발생합니다.

Added in version 3.7.

exception concurrent.futures.interpreter.BrokenInterpreterPool

:exc:`~concurrent.futures.thread.BrokenThreadPool`에서 파생된 이 예외 클래스는 :class:`~concurrent.futures.InterpreterPoolExecutor`의 워커 중 하나가 초기화에 실패했을 때 발생합니다.

Added in version 3.14.

exception concurrent.futures.process.BrokenProcessPool

BrokenExecutor 에서 파생됩니다 (예전에는 RuntimeError), 이 예외 클래스는 ProcessPoolExecutor 의 작업자 중 하나가 깨끗하지 못한 방식으로 (예를 들어, 외부에서 강제 종료된 경우) 종료되었을 때 발생합니다.

Added in version 3.3.

분실물 보관소