8.3. Petlja događaja

Petlja događaja je pogon koji asyncio izvodi ispod svega. Drži popis svih zadataka u programu, traži od svakoga da se izvodi do sljedećeg await tog zadatka i prelazi na sljedeći spreman zadatak. Kad nema spremnih zadataka, čeka – to stvarno čekanje upravo je ono što oslobađa CPU za ugrađeni program da izvodi druge stvari i za uključivanje spavanja radi uštede energije – dok nešto što je zadatak awaitao ne postane dostupno, zatim nastavlja taj zadatak. Ponavlja zauvijek.

Većina aplikacija nikad ne komunicira s petljom izravno. Petlja je posljedica poziva asyncio.run(); aplikacija piše koroutine, raspoređuje ih kao zadatke, a petlja obavlja ostalo.

8.3.1. Što asyncio.run() zapravo radi

Jedan poziv:

asyncio.run(main())

kratica je za dulji niz koraka kojima petlja upravlja u ime aplikacije:

  1. Stvori petlju događaja ako još ne postoji.

  2. Omotaj predanu koroutinu u zadatak i rasporedi je kao ulaznu točku najviše razine petlje.

  3. Pokreni petlju – prolazi kroz spremne zadatke, čeka kad nijedan nije spreman, nastavlja zadatke kad se njihovi awaitovi dovrše – dok zadatak najviše razine ne vrati vrijednost ili podigne iznimku.

  4. Otkaži sve zadatke koje je aplikacija stvorila, a koji se još izvode.

  5. Vrati ono što je koroutina najviše razine vratila (ili ponovno podigni ono što je podigla).

8.3.2. Jedna petlja po programu

MicroPython-ov asyncio ima jednu petlju događaja, i točka. Nema stvaranja nove petlje i nema ugnježđivanja jedne petlje unutar druge. Pozivanje asyncio.run() iznutra koroutine koja se već izvodi na petlji je pogreška; petlja je već tu, a koroutina samo treba awaitati ono što je htjela pokrenuti.

U praksi je pravilo isto kao i završni redak prethodne stranice: postoji točno jedan poziv asyncio.run() po programu, na vrhu, s jednim async def main() iza njega. Sve ostalo živi unutar main.

8.3.3. Izravan pristup petlji

Za rijetke slučajeve u kojima aplikacija treba dotaknuti samu petlju – uglavnom dijagnostiku i rukovatelje iznimaka – asyncio.get_event_loop() vraća objekt Loop. Odande aplikacija može instalirati prilagođeni rukovatelj iznimaka, pregledati što petlja radi ili (vrlo povremeno) pozvati create_task() izravno umjesto asyncio.create_task() (to je ista operacija).

Potpuni skup metoda koje Loop izlaže – run_forever(), stop(), set_exception_handler() i ostale – obrađen je na stranici upravljanje petljom kasnije u ovom odjeljku. Do tada, asyncio.run(main()) jest sve što aplikacija treba.