5

Ich habe zwei Probleme asyncio:Von concurrent.futures mit <a href="https://docs.python.org/3/library/concurrent.futures.html" rel="nofollow noreferrer">concurrent.futures</a>

Wie time.sleep() in einem Python-concurrent.futures brechen?

Fazit: time.sleep() kann nicht unterbrochen werden. Eine Lösung ist: Sie können eine Schleife darum schreiben und kurze Schlüsse machen.

Siehe How to break time.sleep() in a python concurrent.futures

Individuelle Timeouts für concurrent.futures?

Fazit: Individuelle Timeouts müssen vom Benutzer implementiert werden. Zum Beispiel: Sie können für jede Zeitüberschreitung wait() anrufen.

Siehe Individual timeouts for concurrent.futures

Frage

Hat asyncio Thesen Probleme lösen?

+0

Um der Selbsteindämmung, können Sie diese anderen zwei Fragen hier zusammenfassen? – deceze

+0

@deceze, habe ich die Frage aktualisiert und meine Schlussfolgerung hinzugefügt. Ist das ok oder fehlt noch etwas? – guettli

+0

Sieht jetzt antwortbarer aus, danke. – deceze

Antwort

5

Im asyncio-Modell wird die Ausführung durch eine Ereignisschleife geplant und koordiniert. Um die Ausführung einer aktuell ausgesetzten Aufgabe abzubrechen, müssen Sie im Wesentlichen einfach es nicht fortsetzen. Während dies in der Praxis ein wenig anders funktioniert, sollte es offensichtlich sein, dass dies die Aufhebung einer suspendierten Aufgabe in der Theorie einfach macht.

Individuelle Timeouts sind auf die gleiche Art und Weise möglich: Wann immer Sie eine Coroutine anhalten, um auf ein Ergebnis zu warten, möchten Sie einen Timeout-Wert angeben. Die Ereignisschleife stellt sicher, dass die wartende Aufgabe abgebrochen wird, wenn diese Zeitüberschreitung erreicht ist und die Aufgabe noch nicht abgeschlossen ist.

Einige konkrete Beispiele:

>>> import asyncio 
>>> loop = asyncio.get_event_loop() 
>>> task = asyncio.ensure_future(asyncio.sleep(5)) 
>>> task.cancel() 
>>> loop.run_until_complete(task) 
Traceback (most recent call last): 
    ... 
concurrent.futures._base.CancelledError 

In der Praxis könnte dies so etwas wie dies implementiert werden:

class Foo: 
    task = None 

    async def sleeper(self): 
     self.task = asyncio.sleep(60) 
     try: 
      await self.task 
     except concurrent.futures.CancelledError: 
      raise NotImplementedError 

Während diese Methode schläft, kann foo.task.cancel() jemand anderes rufen Sie die Koroutine aufwachen und lass es mit der Stornierung umgehen. Alternativ kann der Anruf sleeper()es direkt stornieren, ohne ihm eine Chance zu geben, aufzuräumen.

Timeouts einstellen ähnlich ist einfach:

>>> loop.run_until_complete(asyncio.wait_for(asyncio.sleep(60), 5)) 
[ ... 5 seconds later ... ] 
Traceback (most recent call last): 
    ... 
concurrent.futures._base.TimeoutError 

Insbesondere im Zusammenhang mit der HTTP-Request-Timeouts finden aiohttp:

async def fetch_page(session, url): 
    with aiohttp.Timeout(10): 
     async with session.get(url) as response: 
      assert response.status == 200 
      return await response.read() 

with aiohttp.ClientSession(loop=loop) as session: 
    content = loop.run_until_complete(fetch_page(session, 'http://python.org')) 

Offensichtlich jeder Aufruf fetch_page auf seinem eigenen aiohttp.Timeout Wert entscheiden können, und Jede einzelne Instanz wird eine eigene Ausnahme auslösen, wenn diese Zeitüberschreitung erreicht ist.

+0

Wow, große Antwort. Vielen Dank. Stellen Sie sich vor, ich benutze das Subprozessmodul (ich lese, dass es unterstützt wird), dann möchte ich den Subprozess irgendwie beenden. Hast du einen Hinweis wie das geht? – guettli

+0

Nicht wirklich, nein.Sie sollten eine neue Frage dafür öffnen. – deceze

+2

@guettli Schauen Sie sich das Modul [asyncio.process] (https://docs.python.org/3/library/asyncio-subprocess.html) und die [Beispiele] (http://asyncio.readthedocs.io) an /latest/subprocess.html). – Vincent

Verwandte Themen