Programování

3 kroky k generální opravě asynchronního prostředí Pythonu

Python je jedním z mnoha jazyků, které podporují určitý způsob psaní asynchronních programů - programů, které volně přepínají mezi více úkoly, všechny běží najednou, takže žádný úkol nezastaví postup ostatních.

Je pravděpodobné, že jste psali hlavně synchronní programy v Pythonu - programy, které dělají pouze jednu věc najednou a čekají na dokončení každého úkolu, než zahájí další. Přechod na async může být nepříjemný, protože vyžaduje naučit se nejen novou syntaxi, ale také nové způsoby myšlení o kódu někoho jiného.

V tomto článku prozkoumáme, jak lze ze stávajícího synchronního programu vytvořit asynchronní program. To zahrnuje více než jen zdobení funkcí asynchronní syntaxí; vyžaduje také přemýšlet jinak o tom, jak náš program běží, a rozhodnout se, zda je async vůbec dobrá metafora toho, co dělá.

[Také na: Naučte se tipy a triky pro Python z videí Smart Python od Serdar Yegulalp]

Kdy použít asynchronní v Pythonu

Program Python je nejvhodnější pro async, pokud má následující vlastnosti:

  • Pokouší se dělat něco, co je většinou vázáno na I / O nebo čekáním na dokončení nějakého externího procesu, jako je dlouhotrvající čtení v síti.
  • Pokouší se dělat jeden nebo více z těchto druhů úkolů najednou, a možná také zpracovává uživatelské interakce.
  • Dotyčné úkoly nejsou výpočetně náročné.

Program v Pythonu, který používá threading, je obvykle dobrým kandidátem na použití async. Vlákna v Pythonu jsou kooperativní; podle potřeby se navzájem poddají. Asynchronní úkoly v Pythonu fungují stejně. Async navíc nabízí určité výhody oproti vláknům:

  • The asynchronní/čekat syntaxe usnadňuje identifikaci asynchronních částí vašeho programu. Naproti tomu je často těžké na první pohled zjistit, které části aplikace běží ve vlákně.
  • Protože asynchronní úkoly sdílejí stejné vlákno, všechna data, ke kterým přistupují, jsou automaticky spravována pomocí GIL (nativní mechanismus Pythonu pro synchronizaci přístupu k objektům). Vlákna často vyžadují složité mechanismy pro synchronizaci.
  • Asynchronní úkoly se snadněji spravují a ruší než vlákna.

Použití async je ne doporučeno, pokud váš program Python má tyto vlastnosti:

  • Úkoly mají vysoké výpočetní náklady - např. Dělají velké problémy s čísly. S těžkou výpočetní prací se nejlépe pracuje multiprocesing, což vám umožňuje věnovat celý Hardware vlákno ke každému úkolu.
  • Úkoly nemají prospěch z prokládání. Pokud každý úkol závisí na posledním, nemá smysl je asynchronně spouštět. To znamená, že pokud program zahrnujesady sériových úkolů můžete každou sadu spustit asynchronně.

Krok 1: Určete synchronní a asynchronní části vašeho programu

Asynchronní kód Pythonu musí být spuštěn a spravován synchronními částmi vaší aplikace Python. Za tímto účelem je vaším prvním úkolem při převodu programu na asynchronní vykreslení čáry mezi synchronizační a asynchronní částí vašeho kódu.

V našem předchozím článku o async jsme jako jednoduchý příklad použili webovou škrabku. Asynchronní části kódu jsou rutiny, které otevírají síťová připojení a čtou z webu - vše, co chcete prokládat. Část programu, která to všechno odstartuje, však není asynchronní; spouští asynchronní úkoly a poté je po dokončení ladně zavře.

Je také důležité potenciálně oddělitblokování z asynchronního a udržujte jej v synchronizované části vaší aplikace. Čtení vstupu uživatele z konzoly například blokuje vše včetně smyčky asynchronních událostí. Proto chcete zpracovat vstup uživatele buď před spuštěním asynchronních úkolů, nebo po jejich dokončení. (To je je možné asynchronně zpracovávat vstupy uživatelů prostřednictvím multiprocesingu nebo threadingu, ale toto je pokročilé cvičení, do kterého se zde nedostaneme.)

Některé příklady operací blokování:

  • Vstup do konzoly (jak jsme právě popsali).
  • Úkoly zahrnující velké využití CPU.
  • Použitím čas. spánek vynutit pauzu. Všimněte si, že můžete spát uvnitř asynchronní funkce pomocí asyncio. spánek jako náhrada za čas. spánek.

Krok 2: Převeďte příslušné synchronizační funkce na asynchronní funkce

Jakmile víte, které části vašeho programu budou běžet asynchronně, můžete je rozdělit na funkce (pokud jste to ještě neudělali) a proměnit je v asynchronní funkce pomocí asynchronní klíčové slovo. Potom budete muset přidat kód do synchronní části aplikace, abyste spustili asynchronní kód a v případě potřeby z něj shromáždili výsledky.

Poznámka: Budete chtít zkontrolovat řetězec volání každé funkce, kterou jste provedli asynchronně, a zajistit, aby nevyvolávala potenciálně dlouhotrvající nebo blokující operaci. Asynchronní funkce mohou přímo volat synchronizační funkce, a pokud to blokuje synchronizační funkce, pak je také volá asynchronní funkce.

Podívejme se na zjednodušený příklad toho, jak by konverze synchronizace na asynchronizaci mohla fungovat. Zde je náš program „před“:

def a_function (): # nějaká akce kompatibilní s async, která chvíli trvá def another_function (): # nějaká synchronizační funkce, ale ne blokující jedna def do_stuff (): a_function () another_function () def main (): for _ in range (3): do_stuff () main () 

Pokud chceme tři instance dělat věci abychom mohli běžet jako asynchronní úkoly, musíme se otočit dělat věci (a potenciálně všeho, čeho se dotkne) do asynchronního kódu. Zde je první průchod při převodu:

import asyncio async def a_function (): # nějaká akce kompatibilní s async, která chvíli trvá def another_function (): # nějaká synchronizační funkce, ale ne blokující jedna async def do__stuff (): čekat a_function () another_function () async def main ( ): tasks = [] pro _ v rozsahu (3): tasks.append (asyncio.create_task (do_stuff ())) čekají asyncio.gather (tasks) asyncio.run (main ()) 

Všimněte si změn, které jsme provedlihlavní. Nyní hlavní používá asyncio spustit každou instanci dělat věci jako souběžný úkol, pak čeká na výsledky (asyncio.gather). Také jsme převedli a_funkce do asynchronní funkce, protože chceme všechny instance a_funkce běžet vedle sebe a vedle všech dalších funkcí, které vyžadují asynchronní chování.

Pokud bychom chtěli jít o krok dále, mohli bychom také konvertovat another_function asynchronizovat:

async def another_function (): # nějaká synchronizační funkce, ale ne blokující jedna async def do_stuff (): await a_function () await another_function () 

Nicméně, dělatanother_function asynchronní by bylo přehnané, protože (jak jsme si všimli) nedělá nic, co by blokovalo pokrok našeho programu. Také, pokud volají nějaké synchronní části našeho programuanother_function, museli bychom je také převést na asynchronní, což by mohlo náš program zkomplikovat, než je třeba.

Krok 3: Důkladně otestujte svůj asynchronní program Pythonu

Jakýkoli asynchronně převedený program je třeba otestovat, než přejde do výroby, aby se zajistilo, že bude fungovat podle očekávání.

Pokud je váš program skromný - řekněme pár desítek řádků - a nepotřebuje kompletní testovací sadu, nemělo by být obtížné ověřit, že funguje podle plánu. To znamená, že pokud převádíte program na asynchronní jako součást většího projektu, kde je testovací sada standardním zařízením, má smysl psát jednotkové testy pro asynchronní i synchronizační komponenty.

Oba hlavní testovací rámce v Pythonu nyní obsahují nějaký druh asynchronní podpory. Python je vlastníunittest framework zahrnuje objekty testovacích případů pro asynchronní funkce a pytest nabídkypytest-asyncio pro stejné konce.

A konečně, při psaní testů pro asynchronní komponenty budete muset jako podmínku testů zacházet s jejich velmi asynchronností. Například neexistuje žádná záruka, že se asynchronní úlohy dokončí v pořadí, v jakém byly zadány. První by mohl přijít jako poslední a některé by se nikdy nedokončily vůbec. Všechny testy, které navrhnete pro asynchronní funkci, musí tyto možnosti zohlednit.

Jak udělat víc s Pythonem

  • Začněte s asynchronizací v Pythonu
  • Jak používat asyncio v Pythonu
  • Jak používat PyInstaller k vytvoření spustitelných souborů Pythonu
  • Výukový program pro Cython: Jak zrychlit Python
  • Jak chytře nainstalovat Python
  • Jak spravovat projekty v Pythonu pomocí Poetry
  • Jak spravovat projekty Pythonu pomocí Pipenv
  • Virtualenv a venv: Vysvětlení virtuálních prostředí Pythonu
  • Python virtualenv a venv dělá a nedělá
  • Vysvětlení vláken a podprocesů v Pythonu
  • Jak používat debugger Pythonu
  • Jak používat timeit k profilování kódu Pythonu
  • Jak používat cProfile k profilování kódu Pythonu
  • Jak převést Python na JavaScript (a zpět)
$config[zx-auto] not found$config[zx-overlay] not found