2.32. Korutiny¶
Korutina je funkce, kterou lze v půli pozastavit a později obnovit od místa, kde skončila, se všemi jejími lokálními proměnnými nedotčenými. Zrcadlí vzor generátoru – tělo funkce, které lze pozastavit a obnovit – s jednou změnou v tom, kdo řídí každé obnovení.
Python má pro psaní korutiny syntaxi v podobě dvojice klíčových slov async / await. async označuje funkci jako korutinu; await označuje uvnitř ní místa, kde je povoleno pozastavení.
2.32.1. Definice korutiny¶
Funkce definovaná pomocí async def je funkce korutiny. Její zavolání nespustí tělo; vrátí objekt korutiny, který se ještě nezačal vykonávat:
async def greet(name):
print("hello,", name)
coro = greet("Alice") # body NOT run yet
Objekt korutiny je pozastaven hned na úplném začátku funkce. Něco ho musí řídit, aby se tělo spustilo – tím něčím je smyčka událostí, runtime komponenta. MicroPython jednu poskytuje v modulu asyncio. Prozatím s korutinou zacházejte jako s „připravenou ke spuštění, čekající na řídicí prvek“.
2.32.2. Pozastavení uvnitř korutiny¶
Uvnitř korutiny výraz await pozastaví vykonávání, dokud není očekávaná hodnota připravena:
async def fetch_and_log():
data = await read_sensor()
print("got:", data)
Když tělo dosáhne await read_sensor(), korutina předá řízení zpět tomu, co ji spouští. Když read_sensor() skončí, řídicí prvek obnoví korutinu na dalším řádku s výsledkem navázaným na data.
await je platné pouze uvnitř korutiny. Jeho použití v běžné funkci je syntaktická chyba.
2.32.3. Vztah ke generátorům¶
Korutiny a generátory sdílejí stejný základní mechanismus. Rozdíl je v tom, kdo táhne každé obnovení:
Generátor poskytuje hodnoty; konzument táhne další pomocí
next()nebo iterací.Korutina poskytuje řízení; smyčka událostí naplánuje obnovení, jakmile je očekávaná operace připravena.
Pokud dává smysl předávací protokol generátoru s yield, předávací protokol korutiny je tatáž myšlenka – jen řízená smyčkou událostí namísto smyčky for.
Smyčka událostí je malý dispečer, který udržuje seznam korutin čekajících na něco (časovač, síťovou událost, dokončení jiné korutiny). V každé iteraci vybere korutinu, jejíž čekání bylo splněno, obnoví ji až do dalšího await, poté zaznamená, na co tato korutina nyní čeká, a přejde na další připravenou. Výsledkem je, že mnoho úloh postupuje souběžně v jediném vlákně – každá korutina dobrovolně předává řízení ve svých bodech await a smyčka tyto okamžiky vyplňuje libovolnými jinými korutinami, které jsou připraveny postoupit.
Pod kapotou await a yield používají stejnou funkci runtime Pythonu pro pozastavení a obnovení funkce. Klíčová slova se liší, protože se liší konvence kolem nich: yield předává hodnotu zpět konzumentovi, který táhne pomocí next(); await předává řízení smyčce událostí, která naplánuje obnovení, jakmile je očekávaná operace připravena. async / await je v podstatě novější syntaxe pro vzor korutiny – starší knihovny stavěly korutiny přímo nad mechanismem generátorů s použitím yield from (zavedeným v Iterátory a generátory) pro delegování pozastavení mezi korutinami.
2.32.4. Korutiny potřebují řídicí prvek¶
Korutina je bez runtime, který by ji řídil, nečinná. Definovat ji je v pořádku; její spuštění potřebuje smyčku událostí. Modul asyncio MicroPythonu tuto smyčku událostí poskytuje. Sekce Asyncio popisuje, jak smyčku spustit, jak na ní naplánovat korutiny, jak mezi nimi sdílet stav pomocí zámků a událostí, jak zacházet se zrušením a časovými limity a jak kolem zde zavedených klíčových slov async / await utvářet reálnou aplikaci.