Was ist der Unterschied zwischen defer.execute()
und threads.deferToThread()
in twisted? Beide nehmen die gleichen Argumente an - eine Funktion und Parameter, mit denen sie aufgerufen werden - und geben eine zurückgestellte zurück, die mit dem Ergebnis des Aufrufs der Funktion ausgelöst wird.
Die threads
version gibt explizit an, dass sie in einem Thread ausgeführt wird. Wenn die defer
-Version jedoch nicht funktioniert, was wäre dann der Aufrufpunkt? Code, der im Reaktor läuft, sollte niemals blockieren, daher muss jede Funktion, die er aufruft, nicht blockieren. Zu diesem Zeitpunkt könnten Sie defer.succeed(f(*args, **kwargs))
anstelle von defer.execute(f, args, kwargs)
mit den gleichen Ergebnissen ausführen.
defer.execute führt die Funktion tatsächlich blockierend im selben Thread aus, und Sie haben Recht, dass defer.execute(f, args, kwargs)
dasselbe tut wie defer.succeed(f(*args, **kwargs))
außer das defer.execute
zurückgibt Ein Callback, bei dem der Fehler ausgelöst wurde, wenn die Funktion f eine Ausnahme auslöst. Wenn in Ihrem defer.succeed-Beispiel die Funktion eine Ausnahme auslöst, würde sie sich nach außen ausbreiten, was nicht erwünscht sein kann.
Zum besseren Verständnis füge ich hier einfach die Quelle von defer.execute ein:
%Vor% Mit anderen Worten, defer.execute
ist nur eine Verknüpfung, um das Ergebnis einer blockierenden Funktion als verzögert zu betrachten, dem Sie dann Rückrufe / Fehler hinzufügen können. Die Callbacks werden mit normaler Verkettungssemantik abgefeuert. Es scheint ein bisschen verrückt, aber Verzögerter kann "feuern" bevor Sie Callbacks hinzufügen und die Callbacks werden immer noch aufgerufen.
Also, um Ihre Frage zu beantworten, warum ist das nützlich ? Nun, defer.execute
eignet sich sowohl zum Testen / Mocking als auch zum einfachen Integrieren einer asynchronen API mit synchronem Code.
Nützlich ist auch defer.maybeDeferred
, das die Funktion aufruft und dann, wenn die Funktion bereits zurückgibt, einfach zurückgibt, ansonsten ähnlich wie defer.execute
. Dies ist nützlich, wenn Sie eine API schreiben, die eine aufrufbare Funktion erwartet, die Ihnen beim Aufrufen eine Verzögerung gibt und Sie auch normale Blockierungsfunktionen akzeptieren möchten.
Nehmen wir zum Beispiel an, Sie hätten eine Anwendung, die Seiten abgerufen und Dinge damit gemacht hat. Und aus irgendeinem Grund mussten Sie dies synchron für einen bestimmten Anwendungsfall ausführen, z. B. in einem Single-Shot-Crontab-Skript oder als Antwort auf eine Anfrage in einer WSGI-Anwendung, aber immer noch dieselbe Codebasis. Wenn Ihr Code so aussieht, könnte es gemacht werden:
%Vor%Um dies in einem synchronen Kontext ohne den Reaktor auszuführen, könnten Sie einfach eine alternative Getter-Funktion übergeben:
%Vor%Tags und Links python multithreading deferred-execution twisted