8.3. De event loop¶
De event loop is de motor die asyncio eronder draait. Hij houdt een lijst bij van elke task in het programma, vraagt elke task om te draaien tot zijn volgende await, en gaat door naar de volgende task die klaar is. Wanneer er geen tasks klaar zijn, wacht hij – het daadwerkelijke wachten is wat de CPU beschikbaar maakt zodat de firmware andere dingen kan draaien en energiebesparende sleeps kunnen ingrijpen – totdat iets waarop een task wachtte beschikbaar komt, en hervat dan die task. Voor altijd herhalen.
De meeste applicaties interageren nooit rechtstreeks met de lus. De lus is een gevolg van het aanroepen van asyncio.run(); de applicatie schrijft coroutines, plant ze als tasks, en de lus doet de rest.
8.3.1. Wat asyncio.run() daadwerkelijk doet¶
Eén aanroep:
asyncio.run(main())
is een afkorting voor een langere reeks die de lus namens de applicatie beheert:
Maak de event loop als deze nog niet bestaat.
Verpak de aangeleverde coroutine in een task en plan deze als het startpunt op het hoogste niveau van de lus.
Draai de lus – doorloop de tasks die klaar zijn, wacht wanneer er geen klaar zijn, hervat tasks wanneer hun awaits voltooid zijn – totdat de task op het hoogste niveau terugkeert of een fout werpt.
Annuleer alle tasks die de applicatie heeft gemaakt en die nog draaien.
Retourneer wat de coroutine op het hoogste niveau ook retourneerde (of werp opnieuw wat hij ook wierp).
8.3.2. Eén lus per programma¶
Asyncio van MicroPython heeft één event loop, punt uit. Er bestaat geen mogelijkheid om een nieuwe lus te maken, en er is geen mogelijkheid om de ene lus in de andere te nesten. Het aanroepen van asyncio.run() vanuit een coroutine die al op de lus draait is een fout; de lus is er al, en de coroutine hoeft alleen maar te awaiten wat hij wilde starten.
In de praktijk is de regel dezelfde als de slotregel van de vorige pagina: er is precies één asyncio.run()-aanroep per programma, bovenaan, met een enkele async def main() erachter. Al het overige leeft binnen main.
8.3.3. Directe toegang tot de lus¶
Voor de zeldzame gevallen waarin een applicatie de lus zelf moet aanraken – voornamelijk diagnostiek en exception-handlers – retourneert asyncio.get_event_loop() het Loop-object. Van daaruit kan de applicatie een aangepaste exception-handler installeren, inspecteren wat de lus doet, of (heel af en toe) rechtstreeks create_task() aanroepen in plaats van asyncio.create_task() (ze zijn dezelfde operatie).
De volledige set methoden die Loop aanbiedt – run_forever(), stop(), set_exception_handler(), en de rest – wordt behandeld op de pagina lusbesturing verderop in dit onderdeel. Tot dan is asyncio.run(main()) alles wat een applicatie nodig heeft.