Programovanie

3 kroky na generálnu opravu asynchrónneho kódu Python

Python je jedným z mnohých jazykov, ktoré určitým spôsobom podporujú písanie asynchrónnych programov - programov, ktoré voľne prepínajú medzi viacerými úlohami, všetky bežia naraz, takže žiadna z úloh neudrží pokrok ostatných.

Je však pravdepodobné, že ste napísali hlavne synchrónne programy v jazyku Python - programy, ktoré robia iba jednu vec naraz a čakajú na dokončenie každej úlohy, až potom začnú ďalšiu. Prechod na asynchronizáciu môže byť nepríjemný, pretože si vyžaduje naučiť sa nielen novú syntax, ale aj nové spôsoby uvažovania o kóde.

V tomto článku sa budeme venovať tomu, ako je možné z existujúceho synchrónneho programu urobiť asynchrónny program. To zahŕňa nielen zdobenie funkcií asynchronnou syntaxou; vyžaduje tiež premýšľať inak o tom, ako náš program beží, a rozhodnúť sa, či je asynchrónna dobrá metafora toho, čo robí.

[Tiež na: Naučte sa tipy a triky pre Python z videí Smart Python od Serdar Yegulalp]

Kedy použiť asynchronizáciu v Pythone

Program Python je najvhodnejší pre asynchronizáciu, ak má nasledujúce vlastnosti:

  • Pokúša sa urobiť niečo, čo je väčšinou viazané na I / O alebo čakať na dokončenie nejakého externého procesu, ako napríklad dlhé čítanie v sieti.
  • Pokúša sa vykonať jeden alebo viac z týchto druhov úloh naraz a prípadne tiež zvládnuť interakcie používateľov.
  • Predmetné úlohy nie sú výpočtovo náročné.

Program Python, ktorý používa vlákna, je zvyčajne dobrým kandidátom na použitie asynchronizácie. Vlákna v Pythone sú kooperatívne; podľa potreby sa navzájom poddávajú. Asynchronné úlohy v Pythone fungujú rovnako. Async navyše ponúka určité výhody oproti vláknam:

  • The async/čakať syntax uľahčuje identifikáciu asynchrónnych častí vášho programu. Naopak, často je ťažké na prvý pohľad povedať, ktoré časti aplikácie sa spúšťajú vo vlákne.
  • Pretože asynchrónové úlohy zdieľajú rovnaké vlákno, všetky dáta, ku ktorým pristupujú, sú spravované automaticky pomocou GIL (natívny mechanizmus Pythonu na synchronizáciu prístupu k objektom). Vlákna často vyžadujú zložité mechanizmy synchronizácie.
  • Asynchronné úlohy sa ľahšie spravujú a rušia ako vlákna.

Používanie asynchronizácie je nie odporúča sa, ak má váš program Python tieto vlastnosti:

  • Úlohy majú vysoké výpočtové náklady - napríklad robia veľké objemy čísel. Najlepšie sa dá zvládnuť náročná výpočtová práca viacprocesové, ktorý umožňuje venovať celý hardvér vlákno ku každej úlohe.
  • Úlohy nemajú úžitok z toho, že sa prekladajú. Ak každá úloha závisí od poslednej, nemá zmysel nútiť ich bežať asynchrónne. To znamená, že ak program zahŕňasady sériových úloh môžete každú sadu spustiť asynchrónne.

Krok 1: Identifikujte synchrónnu a asynchrónnu časť vášho programu

Asynchrónny kód Pythonu musí spúšťať a spravovať synchrónna časť vašej aplikácie Python. Za týmto účelom je vašou prvou úlohou pri prevode programu na asynchrónnu nakresliť čiaru medzi synchronizačnou a asynchrónnou časťou vášho kódu.

V našom predchádzajúcom článku o asynchronizácii sme ako jednoduchý príklad použili aplikáciu webového škrabáka. Asynchronné časti kódu sú rutiny, ktoré otvárajú sieťové pripojenia a čítajú z webu - všetko, čo chcete vložiť. Časť programu, ktorá všetko odštartuje, však nie je asynchronizovaná; spustí asynchrónne úlohy a potom ich po dokončení elegantne uzavrie.

Je tiež dôležité potenciálne oddeliťblokujúca operácia z asynchronizácie a udržiavajte ju v synchronizovanej časti svojej aplikácie. Napríklad čítanie vstupu používateľa z konzoly blokuje všetko vrátane slučky asynchronných udalostí. Preto chcete spracovať vstupy používateľov pred spustením asynchronných úloh alebo po ich dokončení. (To je je možné asynchrónne spracovávať vstupy používateľov pomocou viacerých procesov alebo vlákien, ale toto je pokročilé cvičenie, do ktorého sa tu nedostaneme.)

Niekoľko príkladov blokujúcich operácií:

  • Vstup na konzolu (ako sme práve opísali).
  • Úlohy spojené s veľkým využitím procesora.
  • Použitím čas.spánok vynútiť pauzu. Upozorňujeme, že v asynchronnej funkcii môžete spať pomocou funkcie asyncio.spať ako náhrada za čas.spánok.

Krok 2: Konvertujte príslušné synchronizačné funkcie na asynchrónne

Keď viete, ktoré časti vášho programu budú bežať asynchrónne, môžete ich rozdeliť na funkcie (ak ste to ešte neurobili) a pomocou funkcie async kľúčové slovo. Potom budete musieť pridať kód do synchrónnej časti svojej aplikácie, aby ste spustili asynchrónny kód a v prípade potreby z neho zhromaždili výsledky.

Poznámka: Budete chcieť skontrolovať reťazec volaní každej funkcie, ktorú ste vytvorili asynchrónne, a ubezpečiť sa, že nevyvoláva potenciálne dlhotrvajúcu alebo blokujúcu operáciu. Asynchronné funkcie môžu priamo volať synchronizačné funkcie, a ak tieto synchronizačné funkčné bloky, tak aj asynchronná funkcia, ktorá ich volá.

Pozrime sa na zjednodušený príklad toho, ako by konverzia synchronizácia na asynchronizáciu mohla fungovať. Tu je náš program „pred“:

def a_function (): # nejaká async-kompatibilná akcia, ktorá chvíľu trvá def another_function (): # nejaká synchronizačná funkcia, ale nie blokujúca jedna def do_stuff (): a_function () another_function () def main (): pre _ v dosahu (3): do_stuff () main () 

Ak chceme tri prípady do_stuff aby sme mohli bežať ako asynchronné úlohy, musíme sa obrátiť do_stuff (a potenciálne všetkého, čoho sa dotkne) do asynchrónneho kódu. Tu je prvý prechod pri konverzii:

import asyncio async def a_function (): # nejaká akcia kompatibilná s async, ktorá chvíľu trvá def another_function (): # nejaká synchronizačná funkcia, ale nie blokujúca jedna async def do__stuff (): čaká a_function () another_function () async def main ( ): tasks = [] pre _ v rozsahu (3): tasks.append (asyncio.create_task (do_stuff ())) čakajú asyncio.gather (tasks) asyncio.run (main ()) 

Všimnite si zmeny, ktoré sme vykonalihlavný. Teraz hlavný používa asyncio na spustenie každej inštancie do_stuff ako súbežná úloha, potom čaká na výsledky (asyncio.gather). Tiež sme konvertovali a_funkcia do asynchronnej funkcie, pretože chceme všetky inštancie a_funkcia bežať vedľa seba a popri akýchkoľvek ďalších funkciách, ktoré si vyžadujú asynchronné správanie.

Keby sme chceli ísť o krok ďalej, mohli by sme aj konvertovať another_function asynchronizovať:

async def another_function (): # nejaká synchronizačná funkcia, ale nie blokujúca jedna async def do_stuff (): await a_function () await another_function () 

Avšak výrobaanother_function asynchrónne by bolo prehnané, pretože (ako sme si všimli) nerobí nič, čo by blokovalo pokrok nášho programu. Tiež, ak sa volajú nejaké synchrónne časti nášho programuanother_function, museli by sme ich tiež previesť na asynchrónne, čo by mohlo náš program skomplikovať, ako je potrebné.

Krok 3: Dôkladne otestujte svoj asynchrónny program Python

Akýkoľvek asynchrónne prevedený program je potrebné pred uvedením do výroby otestovať, aby sa zabezpečilo jeho správne fungovanie.

Ak je váš program skromných rozmerov - napríklad niekoľko desiatok riadkov - a nepotrebuje kompletnú testovaciu sadu, potom by nemalo byť ťažké overiť, či funguje tak, ako má. To znamená, že ak prevádzate program na asynchronizáciu ako súčasť väčšieho projektu, kde je testovacia sada štandardným vybavením, má zmysel písať jednotkové testy pre asynchronné aj synchronizované komponenty.

Oba hlavné testovacie rámce v Pythone teraz obsahujú istý druh asynchronnej podpory. Python je vlastnýunittest rámec obsahuje objekty testovacích prípadov pre asynchronné funkcie a pytest ponukypytest-asyncio na rovnaké účely.

Nakoniec, pri písaní testov pre asynchronné komponenty budete musieť ako podmienku testov spracovať ich veľmi asynchrónnosť. Napríklad neexistuje záruka, že sa asynchronné úlohy dokončia v poradí, v akom boli zadané. Prvý by mohol prísť posledný a niektoré by sa nikdy nedokončili vôbec. Všetky testy, ktoré navrhnete pre asynchronnú funkciu, musia zohľadniť tieto možnosti.

Ako urobiť viac s Pythonom

  • Začnite s asynchronizáciou v Pythone
  • Ako používať asyncio v Pythone
  • Ako používať program PyInstaller na vytvorenie spustiteľných súborov Pythonu
  • Výukový program pre Cython: Ako zrýchliť Python
  • Ako inteligentne nainštalovať Python
  • Ako spravovať projekty Pythonu pomocou Poetry
  • Ako spravovať projekty Pythonu pomocou Pipenv
  • Virtualenv a venv: Vysvetlenie virtuálnych prostredí Pythonu
  • Python virtualenv a venv robí a nerobí
  • Vysvetlenie vlákien a podprocesov v jazyku Python
  • Ako používať debugger Pythonu
  • Ako používať timeit na profilovanie kódu Pythonu
  • Ako používať cProfile na profilovanie kódu Pythonu
  • Ako previesť Python na JavaScript (a späť)
$config[zx-auto] not found$config[zx-overlay] not found