concurrent.futures — Starten paralleler Aufgaben

Hinzugefügt in Version 3.2.

Quellcode: Lib/concurrent/futures/thread.py, Lib/concurrent/futures/process.py, und Lib/concurrent/futures/interpreter.py


Das Modul concurrent.futures bietet eine High-Level-Schnittstelle für die asynchrone Ausführung von aufrufbaren Objekten.

Die asynchrone Ausführung kann mit Threads unter Verwendung von ThreadPoolExecutor oder InterpreterPoolExecutor oder separaten Prozessen unter Verwendung von ProcessPoolExecutor erfolgen. Jede implementiert dieselbe Schnittstelle, die durch die abstrakte Klasse Executor definiert ist.

Verfügbarkeit: nicht WASI.

Dieses Modul funktioniert nicht oder ist nicht auf WebAssembly verfügbar. Weitere Informationen finden Sie unter WebAssembly-Plattformen.

Executor-Objekte

class concurrent.futures.Executor

Eine abstrakte Klasse, die Methoden zur asynchronen Ausführung von Aufrufen bereitstellt. Sie sollte nicht direkt verwendet werden, sondern über ihre konkreten Unterklassen.

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

Plant das aufrufbare Objekt, fn, zur Ausführung als fn(*args, **kwargs) und gibt ein Future-Objekt zurück, das die Ausführung des aufrufbaren Objekts repräsentiert.

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)

Ähnlich wie map(fn, *iterables), außer dass

  • Die iterables werden sofort gesammelt und nicht verzögert, es sei denn, es wird eine buffersize angegeben, um die Anzahl der übermittelten Aufgaben zu begrenzen, deren Ergebnisse noch nicht ausgegeben wurden. Wenn der Puffer voll ist, pausiert die Iteration über die iterables, bis ein Ergebnis aus dem Puffer ausgegeben wird.

  • fn wird asynchron ausgeführt und mehrere Aufrufe von fn können gleichzeitig erfolgen.

Der zurückgegebene Iterator löst einen TimeoutError aus, wenn __next__() aufgerufen wird und das Ergebnis nicht nach timeout Sekunden ab dem ursprünglichen Aufruf von Executor.map() verfügbar ist. timeout kann eine Ganzzahl oder eine Gleitkommazahl sein. Wenn timeout nicht angegeben ist oder None ist, gibt es keine Wartezeitbegrenzung.

Wenn ein fn-Aufruf eine Ausnahme auslöst, wird diese Ausnahme ausgelöst, wenn ihr Wert aus dem Iterator abgerufen wird.

Bei Verwendung von ProcessPoolExecutor zerlegt diese Methode iterables in eine Reihe von Blöcken, die sie als separate Aufgaben an den Pool übermittelt. Die (ungefähre) Größe dieser Blöcke kann durch Setzen von chunksize auf eine positive Ganzzahl angegeben werden. Für sehr lange Iterables kann die Verwendung eines großen Wertes für chunksize die Leistung im Vergleich zur Standardgröße von 1 erheblich verbessern. Bei ThreadPoolExecutor und InterpreterPoolExecutor hat chunksize keine Auswirkung.

Geändert in Version 3.5: Parameter chunksize hinzugefügt.

Geändert in Version 3.14: Parameter buffersize hinzugefügt.

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

Signalisiert dem Executor, dass er alle verwendeten Ressourcen freigeben soll, sobald die aktuell anstehenden Futures ausgeführt sind. Aufrufe von Executor.submit() und Executor.map() nach dem Shutdown lösen eine RuntimeError aus.

Wenn wait True ist, gibt diese Methode erst zurück, wenn alle ausstehenden Futures ausgeführt sind und die dem Executor zugeordneten Ressourcen freigegeben wurden. Wenn wait False ist, gibt diese Methode sofort zurück und die dem Executor zugeordneten Ressourcen werden freigegeben, sobald alle ausstehenden Futures ausgeführt sind. Unabhängig vom Wert von wait wird das gesamte Python-Programm erst beendet, wenn alle ausstehenden Futures ausgeführt sind.

Wenn cancel_futures True ist, bricht diese Methode alle ausstehenden Futures ab, die der Executor noch nicht gestartet hat. Bereits abgeschlossene oder laufende Futures werden unabhängig vom Wert von cancel_futures nicht abgebrochen.

Wenn sowohl cancel_futures als auch wait True sind, werden alle Futures, die der Executor gestartet hat, vor der Rückgabe dieser Methode abgeschlossen. Die restlichen Futures werden abgebrochen.

Sie können die explizite Verwendung dieser Methode vermeiden, indem Sie den Executor als Context Manager über die with-Anweisung verwenden, die den Executor herunterfährt (wobei gewartet wird, als wäre Executor.shutdown() mit wait auf True gesetzt aufgerufen worden).

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')

Geändert in Version 3.9: Parameter cancel_futures hinzugefügt.

ThreadPoolExecutor

ThreadPoolExecutor ist eine Unterklasse von Executor, die einen Pool von Threads zur asynchronen Ausführung von Aufrufen verwendet.

Deadlocks können auftreten, wenn der einer Future zugeordnete aufrufbare Aufruf auf die Ergebnisse einer anderen Future wartet. Zum Beispiel

import time
def wait_on_b():
    time.sleep(5)
    print(b.result())  # b will never complete because it is waiting on a.
    return 5

def wait_on_a():
    time.sleep(5)
    print(a.result())  # a will never complete because it is waiting on b.
    return 6


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

Und

def wait_on_future():
    f = executor.submit(pow, 5, 2)
    # This will never complete because there is only one worker thread and
    # it is executing this function.
    print(f.result())

executor = ThreadPoolExecutor(max_workers=1)
executor.submit(wait_on_future)
class concurrent.futures.ThreadPoolExecutor(max_workers=None, thread_name_prefix='', initializer=None, initargs=())

Eine Unterklasse von Executor, die einen Pool von höchstens max_workers Threads zur asynchronen Ausführung von Aufrufen verwendet.

Alle an ThreadPoolExecutor übermittelten Threads werden zusammengeführt, bevor der Interpreter beendet werden kann. Beachten Sie, dass der Behandlungsmechanismus, der dies tut, vor allen mit atexit hinzugefügten Behandlungsmechanismen ausgeführt wird. Das bedeutet, dass Ausnahmen im Hauptthread abgefangen und behandelt werden müssen, um die Threads ordnungsgemäß zu beenden. Aus diesem Grund wird empfohlen, ThreadPoolExecutor nicht für lang andauernde Aufgaben zu verwenden.

initializer ist ein optionales aufrufbares Objekt, das beim Start jedes Worker-Threads aufgerufen wird; initargs ist ein Tupel von Argumenten, die an den Initialisierer übergeben werden. Sollte der initializer eine Ausnahme auslösen, werden alle aktuell anstehenden Jobs eine BrokenThreadPool-Ausnahme auslösen, ebenso jeder Versuch, weitere Jobs an den Pool zu übermitteln.

Geändert in Version 3.5: Wenn max_workers None ist oder nicht angegeben wird, wird es standardmäßig auf die Anzahl der Prozessoren der Maschine multipliziert mit 5 gesetzt, vorausgesetzt, dass ThreadPoolExecutor oft zur Überlappung von E/A-Operationen anstelle von CPU-Arbeit verwendet wird und die Anzahl der Worker höher sein sollte als die Anzahl der Worker für ProcessPoolExecutor.

Geändert in Version 3.6: Parameter thread_name_prefix hinzugefügt, um es Benutzern zu ermöglichen, die Namen der threading.Thread für von dem Pool erstellte Worker-Threads zur einfacheren Fehlerbehebung zu steuern.

Geändert in Version 3.7: Argumente initializer und initargs hinzugefügt.

Geändert in Version 3.8: Der Standardwert für max_workers wird auf min(32, os.cpu_count() + 4) geändert. Dieser Standardwert behält mindestens 5 Worker für E/A-gebundene Aufgaben bei. Er nutzt maximal 32 CPU-Kerne für CPU-gebundene Aufgaben, die den GIL freigeben. Und er vermeidet implizit die Verwendung sehr großer Ressourcen auf Maschinen mit vielen Kernen.

ThreadPoolExecutor wiederverwendet jetzt auch ruhende Worker-Threads, bevor max_workers Worker-Threads gestartet werden.

Geändert in Version 3.13: Der Standardwert für max_workers wird auf min(32, (os.process_cpu_count() or 1) + 4) geändert.

Beispiel für 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/']

# Retrieve a single page and report the URL and contents
def load_url(url, timeout):
    with urllib.request.urlopen(url, timeout=timeout) as conn:
        return conn.read()

# We can use a with statement to ensure threads are cleaned up promptly
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
    # Start the load operations and mark each future with its 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

Die Klasse InterpreterPoolExecutor verwendet einen Pool von Interpretern, um Aufrufe asynchron auszuführen. Sie ist eine Unterklasse von ThreadPoolExecutor, was bedeutet, dass jeder Worker in seinem eigenen Thread läuft. Der Unterschied hierbei ist, dass jeder Worker seinen eigenen Interpreter hat und jede Aufgabe mit diesem Interpreter ausführt.

Der größte Vorteil der Verwendung von Interpretern anstelle von nur Threads ist echte Multi-Core-Parallelität. Jeder Interpreter hat seine eigene Global Interpreter Lock, sodass Code, der in einem Interpreter ausgeführt wird, auf einem CPU-Kern laufen kann, während Code in einem anderen Interpreter ungehindert auf einem anderen Kern läuft.

Der Nachteil ist, dass das Schreiben von parallelem Code für die Verwendung mit mehreren Interpretern zusätzliche Anstrengungen erfordern kann. Dies liegt jedoch daran, dass Sie gezwungen sind, sorgfältig zu überlegen, wie und wann Interpreter interagieren, und explizit zu machen, welche Daten zwischen den Interpretern geteilt werden. Dies führt zu mehreren Vorteilen, die die zusätzliche Anstrengung ausgleichen, einschließlich echter Multi-Core-Parallelität. Zum Beispiel kann Code, der auf diese Weise geschrieben wurde, die Nachvollziehbarkeit von Parallelität erleichtern. Ein weiterer großer Vorteil ist, dass Sie sich nicht mit vielen der großen Probleme bei der Verwendung von Threads befassen müssen, wie z. B. Race Conditions.

Der Interpreter jedes Workers ist von allen anderen Interpretern isoliert. „Isoliert“ bedeutet, dass jeder Interpreter seinen eigenen Laufzeitstatus hat und völlig unabhängig voneinander arbeitet. Wenn Sie beispielsweise sys.stdout in einem Interpreter umleiten, wird er nicht automatisch an einen anderen Interpreter umgeleitet. Wenn Sie ein Modul in einem Interpreter importieren, wird es nicht automatisch in einem anderen importiert. Sie müssten das Modul separat in dem Interpreter importieren, in dem Sie es benötigen. Tatsächlich ist jedes Modul, das in einem Interpreter importiert wird, ein völlig separates Objekt von demselben Modul in einem anderen Interpreter, einschließlich sys, builtins und sogar __main__.

Isolation bedeutet, dass ein veränderbares Objekt oder andere Daten nicht von mehr als einem Interpreter gleichzeitig verwendet werden können. Das bedeutet effektiv, dass Interpreter solche Objekte oder Daten nicht tatsächlich teilen können. Stattdessen muss jeder Interpreter seine eigene Kopie haben, und Sie müssen alle Änderungen zwischen den Kopien manuell synchronisieren. Unveränderliche Objekte und Daten, wie die integrierten Singletons, Zeichenketten und Tupel aus unveränderlichen Objekten, haben diese Einschränkungen nicht.

Die Kommunikation und Synchronisation zwischen Interpretern erfolgt am effektivsten mit dedizierten Werkzeugen, wie sie in PEP 734 vorgeschlagen werden. Eine weniger effiziente Alternative ist die Serialisierung mit pickle und das anschließende Senden der Bytes über einen gemeinsamen socket oder eine pipe.

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

Eine Unterklasse von ThreadPoolExecutor, die Aufrufe asynchron mit einem Pool von höchstens max_workers Threads ausführt. Jeder Thread führt Aufgaben in seinem eigenen Interpreter aus. Die Worker-Interpreter sind voneinander isoliert, was bedeutet, dass jeder seinen eigenen Laufzeitstatus hat und keine veränderbaren Objekte oder andere Daten gemeinsam nutzen kann. Jeder Interpreter hat seine eigene Global Interpreter Lock, was bedeutet, dass mit diesem Executor ausgeführter Code echte Multi-Core-Parallelität aufweist.

Die optionalen Argumente initializer und initargs haben die gleiche Bedeutung wie bei ThreadPoolExecutor: Der Initialisierer wird beim Erstellen jedes Workers ausgeführt, allerdings in diesem Fall im Interpreter des Workers. Der Executor serialisiert den initializer und initargs mithilfe von pickle, wenn er sie an den Interpreter des Workers sendet.

Hinweis

Der Executor kann nicht abgefangene Ausnahmen von initializer durch ExecutionFailed ersetzen.

Andere Hinweise von der Elternklasse ThreadPoolExecutor gelten hier.

submit() und map() funktionieren wie gewohnt, außer dass der Worker das aufrufbare Objekt und die Argumente mit pickle serialisiert, wenn er sie an seinen Interpreter sendet. Der Worker serialisiert ebenso den Rückgabewert, wenn er ihn zurücksendet.

Wenn die aktuelle Aufgabe eines Workers eine nicht abgefangene Ausnahme auslöst, versucht der Worker immer, die Ausnahme unverändert beizubehalten. Wenn dies erfolgreich ist, setzt er außerdem den __cause__ auf eine entsprechende Instanz von ExecutionFailed, die eine Zusammenfassung der ursprünglichen Ausnahme enthält. In dem seltenen Fall, dass der Worker die ursprüngliche Ausnahme nicht unverändert beibehalten kann, speichert er stattdessen direkt die entsprechende Instanz von ExecutionFailed.

ProcessPoolExecutor

Die Klasse ProcessPoolExecutor ist eine Unterklasse von Executor, die einen Pool von Prozessen zur asynchronen Ausführung von Aufrufen verwendet. ProcessPoolExecutor verwendet das Modul multiprocessing, wodurch die Global Interpreter Lock umgangen werden kann, was aber auch bedeutet, dass nur serialisierbare Objekte ausgeführt und zurückgegeben werden können.

Das Modul __main__ muss von Worker-Unterprozessen importierbar sein. Dies bedeutet, dass ProcessPoolExecutor im interaktiven Interpreter nicht funktioniert.

Das Aufrufen von Methoden von Executor oder Future aus einem an einen ProcessPoolExecutor übermittelten aufrufbaren Objekt führt zu einem Deadlock.

Beachten Sie, dass die Einschränkungen für Funktionen und Argumente, die serialisierbar sein müssen, gemäß multiprocessing.Process bei der Verwendung von submit() und map() auf einem ProcessPoolExecutor gelten. Eine Funktion, die in einer REPL oder als Lambda-Funktion definiert ist, sollte nicht erwartet werden, zu funktionieren.

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

Eine Unterklasse von Executor, die Aufrufe asynchron mit einem Pool von höchstens max_workers Prozessen ausführt. Wenn max_workers None ist oder nicht angegeben wird, wird standardmäßig os.process_cpu_count() verwendet. Wenn max_workers kleiner oder gleich 0 ist, wird eine ValueError ausgelöst. Unter Windows muss max_workers kleiner oder gleich 61 sein. Wenn dies nicht der Fall ist, wird eine ValueError ausgelöst. Wenn max_workers None ist, beträgt der gewählte Standardwert höchstens 61, auch wenn mehr Prozessoren verfügbar sind. mp_context kann ein multiprocessing-Kontext oder None sein. Er wird zum Starten der Worker verwendet. Wenn mp_context None ist oder nicht angegeben wird, wird der Standard-multiprocessing-Kontext verwendet. Siehe Kontexte und Startmethoden.

initializer ist ein optionales aufrufbares Objekt, das beim Start jedes Worker-Prozesses aufgerufen wird; initargs ist ein Tupel von Argumenten, die an den Initialisierer übergeben werden. Sollte der initializer eine Ausnahme auslösen, werden alle aktuell anstehenden Jobs eine BrokenProcessPool-Ausnahme auslösen, ebenso jeder Versuch, weitere Jobs an den Pool zu übermitteln.

max_tasks_per_child ist ein optionales Argument, das die maximale Anzahl von Aufgaben angibt, die ein einzelner Prozess ausführen kann, bevor er beendet und durch einen neuen Worker-Prozess ersetzt wird. Standardmäßig ist max_tasks_per_child None, was bedeutet, dass Worker-Prozesse so lange leben, wie der Pool. Wenn ein Maximum angegeben wird, wird standardmäßig die „spawn“-Multiprocessing-Startmethode verwendet, wenn kein mp_context-Parameter angegeben ist. Diese Funktion ist inkompatibel mit der „fork“-Startmethode.

Geändert in Version 3.3: Wenn einer der Worker-Prozesse abrupt beendet wird, wird jetzt ein BrokenProcessPool-Fehler ausgelöst. Zuvor war das Verhalten undefiniert, aber Operationen am Executor oder seinen Futures froren oft ein oder führten zu Deadlocks.

Geändert in Version 3.7: Das Argument mp_context wurde hinzugefügt, um Benutzern die Steuerung der Startmethode für von dem Pool erstellte Worker-Prozesse zu ermöglichen.

Argumente initializer und initargs hinzugefügt.

Geändert in Version 3.11: Das Argument max_tasks_per_child wurde hinzugefügt, um Benutzern die Steuerung der Lebensdauer von Workern im Pool zu ermöglichen.

Geändert in Version 3.12: Auf POSIX-Systemen, wenn Ihre Anwendung mehrere Threads hat und der multiprocessing-Kontext die Startmethode "fork" verwendet: Die intern aufgerufene Funktion os.fork() zum Starten von Workern kann eine DeprecationWarning auslösen. Übergeben Sie einen mp_context, der so konfiguriert ist, dass eine andere Startmethode verwendet wird. Weitere Erläuterungen finden Sie in der Dokumentation zu os.fork().

Geändert in Version 3.13: max_workers verwendet standardmäßig os.process_cpu_count() anstelle von os.cpu_count().

Geändert in Version 3.14: Die Standardmethode zum Starten von Prozessen (siehe Kontexte und Startmethoden) wurde von fork weg geändert. Wenn Sie die fork-Startmethode für ProcessPoolExecutor benötigen, müssen Sie explizit mp_context=multiprocessing.get_context("fork") übergeben.

terminate_workers()

Versucht, alle laufenden Worker-Prozesse sofort durch Aufrufen von Process.terminate für jeden einzelnen zu beenden. Intern wird auch Executor.shutdown() aufgerufen, um sicherzustellen, dass alle anderen mit dem Executor verbundenen Ressourcen freigegeben werden.

Nach dem Aufruf dieser Methode sollte der Aufrufer keine weiteren Aufgaben mehr an den Executor übermitteln.

Hinzugefügt in Version 3.14.

kill_workers()

Versucht, alle laufenden Worker-Prozesse sofort durch Aufrufen von Process.kill für jeden einzelnen zu beenden. Intern wird auch Executor.shutdown() aufgerufen, um sicherzustellen, dass alle anderen mit dem Executor verbundenen Ressourcen freigegeben werden.

Nach dem Aufruf dieser Methode sollte der Aufrufer keine weiteren Aufgaben mehr an den Executor übermitteln.

Hinzugefügt in Version 3.14.

Beispiel für 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-Objekte

Die Klasse Future kapselt die asynchrone Ausführung eines aufrufbaren Objekts. Future-Instanzen werden von Executor.submit() erstellt.

Klasse concurrent.futures.Future

Kapselt die asynchrone Ausführung eines aufrufbaren Objekts. Future-Instanzen werden von Executor.submit() erstellt und sollten nicht direkt erstellt werden, außer zu Testzwecken.

cancel()

Versucht, den Aufruf abzubrechen. Wenn der Aufruf gerade ausgeführt wird oder abgeschlossen ist und nicht abgebrochen werden kann, gibt die Methode False zurück, andernfalls wird der Aufruf abgebrochen und die Methode gibt True zurück.

cancelled()

Gibt True zurück, wenn der Aufruf erfolgreich abgebrochen wurde.

running()

Gibt True zurück, wenn der Aufruf gerade ausgeführt wird und nicht abgebrochen werden kann.

done()

Gibt True zurück, wenn der Aufruf erfolgreich abgebrochen oder abgeschlossen wurde.

result(timeout=None)

Gibt den vom Aufruf zurückgegebenen Wert zurück. Wenn der Aufruf noch nicht abgeschlossen ist, wartet diese Methode bis zu timeout Sekunden. Wenn der Aufruf in timeout Sekunden nicht abgeschlossen ist, wird ein TimeoutError ausgelöst. timeout kann eine ganze Zahl oder ein Float sein. Wenn timeout nicht angegeben ist oder None ist, gibt es keine Wartezeitbegrenzung.

Wenn das Future vor der Fertigstellung abgebrochen wird, wird CancelledError ausgelöst.

Wenn der Aufruf eine Ausnahme ausgelöst hat, löst diese Methode dieselbe Ausnahme aus.

exception(timeout=None)

Gibt die vom Aufruf ausgelöste Ausnahme zurück. Wenn der Aufruf noch nicht abgeschlossen ist, wartet diese Methode bis zu timeout Sekunden. Wenn der Aufruf in timeout Sekunden nicht abgeschlossen ist, wird ein TimeoutError ausgelöst. timeout kann eine ganze Zahl oder ein Float sein. Wenn timeout nicht angegeben ist oder None ist, gibt es keine Wartezeitbegrenzung.

Wenn das Future vor der Fertigstellung abgebrochen wird, wird CancelledError ausgelöst.

Wenn der Aufruf ohne Ausnahme abgeschlossen wurde, wird None zurückgegeben.

add_done_callback(fn)

Hängt das aufrufbare Objekt fn an das Future an. fn wird mit dem Future als einzigem Argument aufgerufen, wenn das Future abgebrochen wird oder abgeschlossen ist.

Hinzugefügte aufrufbare Objekte werden in der Reihenfolge aufgerufen, in der sie hinzugefügt wurden, und immer in einem Thread aufgerufen, der zum Prozess gehört, der sie hinzugefügt hat. Wenn das aufrufbare Objekt eine Unterklasse von Exception auslöst, wird es protokolliert und ignoriert. Wenn das aufrufbare Objekt eine Unterklasse von BaseException auslöst, ist das Verhalten undefiniert.

Wenn das Future bereits abgeschlossen oder abgebrochen wurde, wird fn sofort aufgerufen.

Die folgenden Future-Methoden sind für die Verwendung in Unit-Tests und Executor-Implementierungen vorgesehen.

set_running_or_notify_cancel()

Diese Methode sollte nur von Executor-Implementierungen vor der Ausführung der mit dem Future verbundenen Arbeit und von Unit-Tests aufgerufen werden.

Wenn die Methode False zurückgibt, wurde das Future abgebrochen, d. h. Future.cancel() wurde aufgerufen und gab True zurück. Alle Threads, die auf die Fertigstellung des Future warten (d. h. über as_completed() oder wait()), werden geweckt.

Wenn die Methode True zurückgibt, wurde das Future nicht abgebrochen und wurde in den laufenden Zustand versetzt, d. h. Aufrufe von Future.running() geben True zurück.

Diese Methode kann nur einmal aufgerufen werden und kann nicht nach dem Aufruf von Future.set_result() oder Future.set_exception() aufgerufen werden.

set_result(result)

Legt das Ergebnis der mit dem Future verbundenen Arbeit auf result fest.

Diese Methode sollte nur von Executor-Implementierungen und Unit-Tests verwendet werden.

Geändert in Version 3.8: Diese Methode löst concurrent.futures.InvalidStateError aus, wenn das Future bereits abgeschlossen ist.

set_exception(exception)

Legt das Ergebnis der mit dem Future verbundenen Arbeit auf die Exception exception fest.

Diese Methode sollte nur von Executor-Implementierungen und Unit-Tests verwendet werden.

Geändert in Version 3.8: Diese Methode löst concurrent.futures.InvalidStateError aus, wenn das Future bereits abgeschlossen ist.

Modulfunktionen

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

Wartet auf die Fertigstellung der Future-Instanzen (möglicherweise erstellt von verschiedenen Executor-Instanzen), die durch fs angegeben sind. Doppelte Futures in fs werden entfernt und nur einmal zurückgegeben. Gibt ein benanntes 2-Tupel von Mengen zurück. Die erste Menge, genannt done, enthält die Futures, die vor Abschluss des Wartens abgeschlossen wurden (fertige oder abgebrochene Futures). Die zweite Menge, genannt not_done, enthält die Futures, die nicht abgeschlossen wurden (ausstehende oder laufende Futures).

timeout kann verwendet werden, um die maximale Anzahl von Sekunden zu steuern, die gewartet werden soll, bevor zurückgekehrt wird. timeout kann eine ganze Zahl oder ein Float sein. Wenn timeout nicht angegeben ist oder None ist, gibt es keine Wartezeitbegrenzung.

return_when gibt an, wann diese Funktion zurückkehren soll. Es muss eine der folgenden Konstanten sein:

Konstante

Beschreibung

concurrent.futures.FIRST_COMPLETED

Die Funktion wird zurückkehren, wenn ein Future abgeschlossen oder abgebrochen wird.

concurrent.futures.FIRST_EXCEPTION

Die Funktion wird zurückkehren, wenn ein Future durch Auslösen einer Ausnahme abgeschlossen wird. Wenn kein Future eine Ausnahme auslöst, ist dies äquivalent zu ALL_COMPLETED.

concurrent.futures.ALL_COMPLETED

Die Funktion wird zurückkehren, wenn alle Futures abgeschlossen oder abgebrochen werden.

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

Gibt einen Iterator über die Future-Instanzen (möglicherweise erstellt von verschiedenen Executor-Instanzen) zurück, die durch fs gegeben sind, und liefert Futures, sobald sie abgeschlossen sind (fertige oder abgebrochene Futures). Duplizierte Futures in fs werden einmal zurückgegeben. Futures, die vor dem Aufruf von as_completed() abgeschlossen wurden, werden zuerst geliefert. Der zurückgegebene Iterator löst ein TimeoutError aus, wenn __next__() aufgerufen wird und das Ergebnis nach timeout Sekunden ab dem ursprünglichen Aufruf von as_completed() nicht verfügbar ist. timeout kann eine ganze Zahl oder ein Float sein. Wenn timeout nicht angegeben ist oder None ist, gibt es keine Wartezeitbegrenzung.

Siehe auch

PEP 3148 – Futures - Berechnungen asynchron ausführen

Der Vorschlag, der diese Funktion für die Aufnahme in die Python-Standardbibliothek beschrieb.

Ausnahmeklassen

Ausnahme concurrent.futures.CancelledError

Wird ausgelöst, wenn ein Future abgebrochen wird.

Ausnahme concurrent.futures.TimeoutError

Ein veralteter Alias für TimeoutError, der ausgelöst wird, wenn eine Future-Operation das angegebene Timeout überschreitet.

Geändert in Version 3.11: Diese Klasse wurde zu einem Alias von TimeoutError.

Ausnahme concurrent.futures.BrokenExecutor

Diese Ausnahme, die von RuntimeError abgeleitet ist, wird ausgelöst, wenn ein Executor aus irgendeinem Grund beschädigt ist und nicht zum Übermitteln oder Ausführen neuer Aufgaben verwendet werden kann.

Hinzugefügt in Version 3.7.

Ausnahme concurrent.futures.InvalidStateError

Wird ausgelöst, wenn eine Operation auf einem Future ausgeführt wird, die im aktuellen Zustand nicht zulässig ist.

Hinzugefügt in Version 3.8.

Ausnahme concurrent.futures.thread.BrokenThreadPool

Diese Ausnahme, die von BrokenExecutor abgeleitet ist, wird ausgelöst, wenn einer der Worker eines ThreadPoolExecutor bei der Initialisierung fehlgeschlagen ist.

Hinzugefügt in Version 3.7.

Ausnahme concurrent.futures.interpreter.BrokenInterpreterPool

Diese Ausnahme, die von BrokenThreadPool abgeleitet ist, wird ausgelöst, wenn einer der Worker eines InterpreterPoolExecutor bei der Initialisierung fehlgeschlagen ist.

Hinzugefügt in Version 3.14.

Ausnahme concurrent.futures.interpreter.ExecutionFailed

Wird von InterpreterPoolExecutor ausgelöst, wenn der angegebene Initialisierer fehlschlägt, oder von submit(), wenn eine nicht abgefangene Ausnahme aus der übermittelten Aufgabe auftritt.

Hinzugefügt in Version 3.14.

Ausnahme concurrent.futures.process.BrokenProcessPool

Diese Ausnahme, die von BrokenExecutor (früher RuntimeError) abgeleitet ist, wird ausgelöst, wenn einer der Worker eines ProcessPoolExecutor auf eine nicht saubere Weise beendet wurde (z. B. wenn er von außen beendet wurde).

Hinzugefügt in Version 3.3.