Das synchrone Python SDK aus asyncio verwenden

Von solvethree3 Min. Lesezeit

Verwenden Sie asyncio.to_thread, um die synchrone Methode Solvethree.solve auszuführen, ohne Ihre Ereignisschleife zu blockieren. Begrenzen Sie die Auslagerung mit einem Semaphor und erstellen Sie innerhalb jedes Worker-Aufrufs einen eigenen Client. Das SDK hat keinen nativen asynchronen Client; seine Anfragen und das Polling laufen im Thread weiterhin synchron.

Auf dieser Seite

Parallelität begrenzen und die SDK-Frist festlegen

Das Beispiel erfordert Python 3.10+ und das offizielle Python-SDK. Setzen Sie SOLVETHREE_API_KEY und SOLVETHREE_PROXY in Ihrer Serverumgebung. Ersetzen Sie accounts.example.com und login durch den Hostnamen und die Aktion Ihres Ziels. Für die Site muss bereits ein aktives Profil in Ihrem Workspace verfügbar sein; siehe Site-Profil einrichten.

asyncio · Synchrone SDK-Arbeit begrenzen
import asyncio
import os
import uuid
from solvethree import Solvethree

async def main():
    limit = asyncio.Semaphore(4)
    async def solve_one(number):
        task = {"site": "accounts.example.com", "action": "login", "proxy": os.environ["SOLVETHREE_PROXY"], "requestId": str(uuid.uuid4())}
        def blocking_solve():
            return Solvethree(os.environ["SOLVETHREE_API_KEY"]).solve(task, timeout=180)
        async with limit:
            try:
                result = await asyncio.to_thread(blocking_solve)
                print("Ready task:", result["id"])
                # Submit the solution now with its proxy and browser identity.
            except Exception as error:
                print("Job", number, "requestId", task["requestId"], "error class", type(error).__name__)
                # Retain task and inspect SDK recovery IDs before restarting it.
    await asyncio.gather(*(solve_one(number) for number in range(8)))

asyncio.run(main())
# Canceling an await does not stop an already-running thread or remote task.
  • Der Semaphor lässt von den acht an gather übergebenen Jobs jeweils vier gleichzeitig zu. Jobs, die auf einen freien Platz warten, haben ihren SDK-Aufruf noch nicht gestartet.
  • Jeder Worker erstellt seinen eigenen Solvethree-Client, statt einen Client zwischen Threads zu teilen.
  • Das SDK legt mit timeout=180 die Frist für das Lösen fest. Die Wartezeit auf den Semaphor wird nicht mitgezählt. Ein asyncio-Timeout um das await ersetzt diese SDK-Frist nicht.
  • Der Task und seine requestId werden vor dem Eintritt in den Worker erstellt. Halten Sie beide für die Wiederherstellung verfügbar, statt bei jedem Fehler eine Ersatz-ID zu generieren.

Das SDK erstellt den Task einmal und fragt ihn ab, bis er bereit ist oder ein Fehler ausgelöst wird. Sie müssen keine zweite Polling-Schleife um solve schreiben.

Ein Abbruch stoppt weder den Worker noch den serverseitigen Task

Das Abbrechen der Coroutine, die auf to_thread wartet, stoppt keinen bereits laufenden Thread und bricht den serverseitigen Lösevorgang nicht ab. Der gewöhnliche Exception-Handler des Beispiels übernimmt keine Aufräumarbeiten bei einem Abbruch.

Das betrifft auch die Parallelitätsgrenze: Ein Abbruch kann den Semaphor freigeben, während der Worker weiterläuft. Wenn Sie sofort Ersatzjobs zulassen, können mehr als vier SDK-Aufrufe aktiv bleiben. Wenn Sie auch bei Abbrüchen eine strikte Grenze benötigen, verfolgen Sie noch laufende Worker und halten Sie deren Kapazität bis zu ihrem Abschluss belegt.

Bewahren Sie im Produktionsbetrieb die exakten Task-Eingaben und die Anfrage-ID an einem Ort auf, auf den Ihr Wiederherstellungspfad auch nach dem Ende der Coroutine zugreifen kann. Ein Timeout bedeutet, dass Sie kein Ergebnis mehr empfangen, nicht unbedingt, dass die Task-Erstellung fehlgeschlagen ist.

  1. 1.

    Einen bekannten Task wiederaufnehmen

    Prüfen Sie task_id und request_id im Fehler des Python-SDKs. Wenn Sie eine Task-ID haben, setzen Sie den Abruf mit get_task fort, statt einen weiteren Task zu erstellen.

  2. 2.

    Eine unterbrochene Erstellung wiederherstellen

    Wenn Sie keine Task-ID haben, senden Sie die identischen Task-Eingaben mit der ursprünglichen requestId erneut. War die Erstellung erfolgreich, wird der bestehende Task zurückgegeben. Wenn Sie bei Wiederverwendung dieser ID die Eingaben ändern, entsteht ein Konflikt.

  3. 3.

    Fehlschlag und Unterbrechung unterscheiden

    Ein TaskFailedError bedeutet, dass der Task den endgültigen Fehlerstatus erreicht hat. Prüfen Sie seine Felder errorCode und error; fragen Sie ihn nicht weiter ab und wiederholen Sie unveränderte ungültige Eingaben nicht blind. HTTP-Fehler bilden eine separate Fehlerebene.

Die Lösung übermitteln, sobald der Worker zurückkehrt

Das Beispiel gibt die ID des bereiten Tasks aus; es übermittelt nichts an das Ziel. Ersetzen Sie den Kommentar nach dieser Ausgabe durch Ihre anwendungsspezifische Übermittlung und verwenden Sie die Lösung zeitnah, statt auf den Abschluss aller Jobs in gather zu warten.

Übermitteln Sie die zurückgegebene Lösung mit ihrem userAgent, secChUa und demselben Proxy, der zum Lösen verwendet wurde. Die Hilfsfunktion successful_proxy des SDKs wählt den Proxy aus dem ursprünglichen Task und dem ready-Ergebnis aus. Ein ready-Ergebnis bedeutet, dass eine Lösung generiert wurde, nicht, dass Ihre Anwendungsanfrage erfolgreich war.

Führe deinen ersten Task aus.

Starte mit $5 Workspace-Guthaben.

Workspace erstellen
Das synchrone Python SDK aus asyncio verwenden · solvethree