Konvertieren Sie die asynchrone API im Callback-Stil in async / await in Python

Überblick

Seit Python 3.5 ist async / await für die asynchrone Programmierung verfügbar. Viele vorhandene Bibliotheken verfügen jedoch über eine herkömmliche asynchrone API vom Rückruftyp, und async / await kann nicht so angewendet werden, wie es ist. Daher werden wir eine solche Rückruf-API in ein Formular konvertieren, das mit async / await verwendet werden kann.

Beispiel für eine asynchrone API vom Rückruftyp

Fügt die Argumente a und b zu einem anderen Thread hinzu und gibt das Ergebnis in einem Rückruf zurück Betrachten Sie die folgende async_add-Methode.

import time
import threading

def async_add(a, b, callback):
    def run():
        time.sleep(1)
        callback(a + b)
    thread = threading.Thread(target=run)
    thread.start()

Verwenden wir dies, um eine 1 + 2 + 3-Berechnung durchzuführen. Es wird wie folgt sein.

async_add(1, 2, lambda result1: \
        async_add(result1, 3, lambda result2: \
                print(result2)))

Es ist kompliziert, weil die Rückrufe verschachtelt sind. Ich möchte dies zusammenfassen, damit ich mit wait ein Bild wie das folgende schreiben kann:

result1 = await awaitable_async_add(1, 2)
result2 = await awaitable_async_add(result1, 3)
print(result2)

Implementierung

Code

import time
import threading
import asyncio

def async_add(a, b, callback):
    def run():
        time.sleep(1)
        callback(a + b)
    thread = threading.Thread(target=run)
    thread.start()

def awaitable_async_add(a, b, loop):
    f = asyncio.Future() # (1)
    def callback(result):
        loop.call_soon_threadsafe(
                lambda: f.set_result(result)) #(2)
    async_add(a, b, callback) # (1)
    return f # (1)

async def exec(loop):
    result1 = await awaitable_async_add(1, 2, loop)
    result2 = await awaitable_async_add(result1, 3, loop)
    print(result2)

loop = asyncio.get_event_loop() # (3)
loop.run_until_complete(exec(loop)) # (3)
loop.stop()

Ausführungsergebnis

6

Kommentar

(1) Wenn die Methode awaitable_async_add aufgerufen wird, wird die Ausführung der Methode async_add gestartet und das Objekt asyncio.Future wird sofort zurückgegeben. Zu diesem Zeitpunkt ist der Berechnungsprozess noch nicht abgeschlossen.

(2) Der Rückruf wird aufgerufen, wenn der Berechnungsprozess abgeschlossen ist. Durch Aufrufen der set_result () -Methode des asyncio.Future-Objekts mit dem Verarbeitungsergebnis als Argument wird das asyncio.Future-Objekt über den Abschluss der Verarbeitung benachrichtigt und das Berechnungsergebnis zurückgegeben.

(3) Erfassen Sie eine Ereignisschleife und führen Sie den Prozess aus, bis der asynchrone Prozess abgeschlossen ist.

Eine Sache, die hier zu beachten ist, ist loop.call_soon_threadsafe in (2). Wenn Sie versuchen, f.set_result wie unten gezeigt direkt aufzurufen, tritt ein Fehler auf.

    def callback(result):
        f.set_result(result)

Ausführungsergebnis

RuntimeError: Non-thread-safe operation invoked on an event loop other than the current one

Dieser Fehler ist darauf zurückzuführen, dass die Methode set_result in einem anderen Thread als der in (3) ausgeführten Ereignisschleife aufgerufen wird. Da asyncio.Future nicht threadsicher ist, muss die Methode set_result immer im selben Thread wie die Ereignisschleife aufgerufen werden. Daher wird set_result in der Ereignisschleife aufgerufen, indem die Verarbeitung als Rückruf an die Methode call_soon_threadsafe der Ereignisschleife übergeben wird.

Referenz

https://docs.python.org/3.6/library/asyncio.html

Recommended Posts

Konvertieren Sie die asynchrone API im Callback-Stil in async / await in Python
Konvertieren Sie Markdown in Python in PDF
Verstecke Websockets asynchron / warte in Python3
[Python] Asynchrone Anfrage mit async / await
Konvertieren Sie die psd-Datei in Python in png
In Python von Markdown in HTML konvertieren
Konvertieren Sie die absolute URL in eine relative URL in Python
Konvertieren Sie PDFs mit Python in Massenbilder
Konvertieren Sie den exponentiellen Float in Python in str
Konvertieren Sie kubischen Netzcode in Python in WKT
Python async / warte auf Kuriosität
C-API in Python 3
Konvertieren Sie Datum und Uhrzeit in Zeitzonen in Unixtime in Python2.7
So konvertieren / wiederherstellen Sie einen String mit [] in Python
Konvertieren Sie das NumPy-Array "ndarray" in Python [tolist ()]
Konvertieren Sie die Netzmaske der CIDR-Notation in Python in eine gepunktete Dezimalschreibweise
So konvertieren Sie Gleitkommazahlen in Python in Binärzahlen
Konvertieren Sie das Bild in .zip mit Python in PDF
Konvertieren / Zurückgeben von Klassenobjekten in das JSON-Format in Python
Asynchrone Verarbeitung von Python ~ Asynchron vollständig verstehen und warten ~
[Python] Erstellt eine Methode zum Konvertieren von Radix in 1 Sekunde
Konvertieren Sie den Webpay-Entitätstyp in den Dict-Typ (rekursiv in Python).
Hit Mastodons API in Python
Scraping mit Python 3.5 async / await
So löschen Sie stdout in Python
Konvertieren Sie numpy int64 in python int
[Python] Liste in Pandas konvertieren [Pandas]
Melden Sie sich auf der Website in Python an
Asynchrone Verarbeitung (Threading) in Python
Konvertieren Sie das Scratch-Projekt in Python
[Python] Konvertieren Sie Shift_JIS in UTF-8
Konvertieren Sie die CIDR-Notation in Python
Sprechen mit Python [Text zu Sprache]
Blender Python API in Houdini (Python 3)
Wie man in Python entwickelt
Konvertieren Sie Python 3.x-Code in Python 2.x.
Post an Slack in Python
Leichter Thread-Leistungsbenchmark mit async / await, implementiert in Python 3.5
Ich habe versucht, API list.csv mit Python aus swagger.yaml zu erstellen
Konvertieren Sie das an Jason Stay Samlike in Python übergebene Bild in ASCII Art
Konvertieren Sie eine Excel-Datei für verschiedene Zwecke in Python in Text
Rufen Sie github api in Python auf, um Informationen zur Pull-Anforderung zu erhalten
Eine einfache Möglichkeit, die Amazon-Produkt-API in Python aufzurufen
Bestimmen Sie das Datums- und Uhrzeitformat mit Python und konvertieren Sie es in Unixtime
[Python] Wie man PCA mit Python macht
Abrufen der arXiv-API in Python
So sammeln Sie Bilder in Python
Klicken Sie in Python auf die Sesami-API
Konvertieren Sie in Python usw. geschriebene Dateien in PDF mit Syntax-Hervorhebung
Verwendung von SQLite in Python
Workflow zum Konvertieren der Formel (Bild) in Python
Konvertieren Sie die Liste mit Python in DataFrame
Lesen Sie die Big-Endian-Binärdatei in Python und konvertieren Sie sie in ndarray
Versuchen Sie, Trace in Python zu berechnen
So konvertieren Sie 0,5 in 1056964608 auf einmal
Klicken Sie in Python auf die New Relic-API, um den Status des Servers abzurufen
Erstellen Sie Google Mail in Python ohne Verwendung der API
Python> Liste> Doppelte Liste in einfache Liste konvertieren
Klicken Sie auf die Web-API in Python
Wie man MySQL mit Python benutzt