8.3. Händelseloopen¶
Händelseloopen är motorn som asyncio kör under huven. Den håller en lista över varje uppgift i programmet, ber var och en att köra till uppgiftens nästa await och går vidare till nästa redo uppgift. När det inte finns några redo uppgifter väntar den – den faktiska väntan är vad som gör processorn tillgänglig för att den fasta programvaran ska köra andra saker och för att strömsparande sömner ska träda in – tills något som en uppgift väntade på blir tillgängligt, och återupptar sedan den uppgiften. Upprepa i all evighet.
De flesta applikationer interagerar aldrig direkt med loopen. Loopen är en följd av att anropa asyncio.run(); applikationen skriver coroutiner, schemalägger dem som uppgifter, och loopen sköter resten.
8.3.1. Vad asyncio.run() faktiskt gör¶
Ett enda anrop:
asyncio.run(main())
är en förkortning för en längre sekvens som loopen hanterar för applikationens räkning:
Skapa händelseloopen om den inte redan finns.
Förpacka den medskickade coroutinen i en uppgift och schemalägg den som loopens ingångspunkt på toppnivå.
Kör loopen – gå igenom redo uppgifter, vänta när inga är redo, återuppta uppgifter när deras await:er slutförs – tills uppgiften på toppnivå returnerar eller kastar.
Avbryt alla uppgifter som applikationen skapat och som fortfarande körs.
Returnera vad coroutinen på toppnivå returnerade (eller återkasta vad den kastade).
8.3.2. En enda loop per program¶
MicroPythons asyncio har en händelseloop, punkt slut. Det går inte att skapa en ny loop, och det går inte att nästla en loop inuti en annan. Att anropa asyncio.run() från en coroutine som redan körs på loopen är ett fel; loopen finns redan där, och coroutinen behöver bara await:a det den ville starta.
I praktiken är regeln densamma som slutraden på föregående sida: det finns exakt ett asyncio.run()-anrop per program, högst upp, med en enda async def main() bakom sig. Allt annat lever inuti main.
8.3.3. Direkt loopåtkomst¶
För de sällsynta fall då en applikation behöver röra själva loopen – mest diagnostik och undantagshanterare – returnerar asyncio.get_event_loop() Loop-objektet. Därifrån kan applikationen installera en anpassad undantagshanterare, inspektera vad loopen gör, eller (mycket sällan) anropa create_task() direkt istället för asyncio.create_task() (de är samma operation).
Den fullständiga uppsättningen metoder som Loop exponerar – run_forever(), stop(), set_exception_handler() och resten – behandlas på sidan loopstyrning senare i detta avsnitt. Fram till dess är asyncio.run(main()) allt en applikation behöver.