Derzeit habe ich einen ineffizienten synchronen Generator, der viele HTTP-Anfragen nacheinander absetzt und die Ergebnisse liefert. Ich möchte asyncio
und aiohttp
verwenden, um die Anfragen parallel zu machen und dadurch diesen Generator zu beschleunigen, aber ich möchte es als ein gewöhnlicher Generator behalten (nicht PEP 525 async generator), damit der Nicht-Async-Code, der es aufruft, nicht muss modifiziert sein. Wie kann ich einen solchen Generator erstellen?Generator erstellen, der Coroutine-Ergebnisse liefert, wenn die Koroutinen beendet werden
Antwort
asyncio.as_completed()
, derzeit kaum dokumentiert, nimmt eine iterable von Coroutines oder Futures und gibt eine iterable von Futures in der Reihenfolge, dass die Input-Futures abgeschlossen. Normalerweise, würden Sie eine Schleife über das Ergebnis und await
die Mitglieder aus dem Innern einer async
Funktion ...
import asyncio
async def first():
await asyncio.sleep(5)
return 'first'
async def second():
await asyncio.sleep(1)
return 'second'
async def third():
await asyncio.sleep(3)
return 'third'
async def main():
for future in asyncio.as_completed([first(), second(), third()]):
print(await future)
loop = asyncio.get_event_loop()
# Prints 'second', then 'third', then 'first'
loop.run_until_complete(main())
... aber für die Zwecke dieser Frage, wollen, was wir liefern zu können, ist zu diese Ergebnisse stammen von einem gewöhnlichen Generator, so dass normaler synchroner Code sie verbrauchen kann, ohne jemals zu wissen, dass async
Funktionen unter der Haube verwendet werden. Wir können das tun, indem loop.run_until_complete()
an den Termin von unseren as_completed
Anruf ergab Aufruf ...
import asyncio
async def first():
await asyncio.sleep(5)
return 'first'
async def second():
await asyncio.sleep(1)
return 'second'
async def third():
await asyncio.sleep(3)
return 'third'
def ordinary_generator():
loop = asyncio.get_event_loop()
for future in asyncio.as_completed([first(), second(), third()]):
yield loop.run_until_complete(future)
# Prints 'second', then 'third', then 'first'
for element in ordinary_generator():
print(element)
Auf diese Weise können wir unsere Asynchron-Code nicht-Asynchron-Land in einer Weise ausgesetzt haben, die nicht benötigt Anrufer, um irgendwelche Funktionen wie async
zu definieren, oder sogar zu wissen, dass ordinary_generator
asyncio
unter der Haube verwendet.
Als eine alternative Implementierung von ordinary_generator()
, die mehr Flexibilität in einigen Fällen bietet, können wir immer wieder asyncio.wait()
mit der FIRST_COMPLETED
Flagge rufen statt Schleifen über as_completed()
:
import concurrent.futures
def ordinary_generator():
loop = asyncio.get_event_loop()
pending = [first(), second(), third()]
while pending:
done, pending = loop.run_until_complete(
asyncio.wait(
pending,
return_when=concurrent.futures.FIRST_COMPLETED
)
)
for job in done:
yield job.result()
Diesen Ansatz, der eine Liste von pending
Erhaltung von Arbeitsplätzen, hat den Vorteil, dass wir es anpassen können, um Aufträge auf der pending
Liste im laufenden Betrieb hinzuzufügen. Dies ist nützlich in Anwendungsfällen, in denen unsere asynchronen Jobs der Warteschlange eine unvorhersehbare Anzahl weiterer Jobs hinzufügen können - wie eine Webspinne, die allen Links auf jeder Seite folgt, die sie besucht.
- 1. C++ - Koroutinen/Visual Studio: Wie kann ein Generator eine Funktion aufrufen, die Werte in seinem Namen liefert?
- 2. Pylint, Koroutinen, Dekorateure und die Typenanalyse
- 3. Python-Funktion, die sowohl Generator- als auch Aggregat-Ergebnisse liefert
- 4. Der Alarm wird beendet, wenn das Betriebssystem die App beendet
- 5. Wie kann ein Generator in eine Funktion umgewandelt werden, die nur den ersten vom Generator gelieferten Wert liefert?
- 6. Ausbrechen einer Schleife, wenn Benutzereingaben beendet oder beendet werden C#
- 7. Versucht, das Konzept der Koroutinen auf vorhandenen Code
- 8. Android: Wie Ressourcen freigegeben werden, wenn die Anwendung beendet wird?
- 9. Wie benachrichtigt werden, wenn scrollToRowAtIndexPath beendet
- 10. Wie man darauf wartet, dass Koroutinen synchron innerhalb der Methode abgeschlossen werden, wenn die Ereignisschleife bereits läuft?
- 11. Koroutinen und while-Schleife
- 12. C++/cx-Koroutinen: einfache Schleife Beispiel
- 13. Wie kann man die Druckausgabe vom Generator sehen, bevor der Zyklus beendet wird?
- 14. Gegenseitig rekursive Koroutinen mit asyncio
- 15. Koroutinen in Python mit Rendite
- 16. Erstellen Instagram Access Token Generator
- 17. Werden Java-Daemon-Threads automatisch beendet, wenn ihre Eltern beendet werden?
- 18. UploadServiceBroadcastReceiver wird beendet, wenn die Aktivität beendet ist
- 19. Wann soll die Hibernate-Sitzung beendet werden?
- 20. Wann sollte die Zeitüberschreitung der Ergebnisse automatisch beendet werden?
- 21. Update-Feld, wenn Funktion die Berechnungen beendet
- 22. Der Timer ist beendet, wenn die Ansicht wechselt
- 23. PyCharm: Wie dokumentieren: rtype: für Funktion, Generator liefert
- 24. Random String Generator Javascript - While Schleife
- 25. Wie werden FCM-ähnliche Dienste für die Remote-Benachrichtigung erstellt, wenn die App beendet wird?
- 26. Javascript: Bearbeiten, wenn der Benutzer die Eingabe beendet hat
- 27. Beenden der untergeordneten Aktivität, wenn die übergeordnete Aktivität beendet wird
- 28. Dokumentieren von Python-Koroutinen mit Sphinx autodoc
- 29. Benachrichtigung pendingInteent contentIntent schlägt fehl, wenn Aktivitätsaufrufe beendet werden()
- 30. Wie kann der Scanner beendet werden, wenn die Eingabe abgeschlossen ist?
Benötigen diese eine 'loop.close()'? – Neil