Programavimas

3 žingsniai iki „Python“ asinchroninio remonto

„Python“ yra viena iš daugelio „Windows“ versijų, palaikančių tam tikrą būdą rašyti asinchronines programas - programas, kurios laisvai persijungia tarp kelių užduočių, visos veikia vienu metu, todėl nė viena užduotis nesulaiko kitų pažangos.

Vis dėlto yra tikimybė, kad daugiausia rašėte sinchronines „Python“ programas - programas, kurios vienu metu atlieka tik vieną dalyką, laukdami, kol kiekviena užduotis bus baigta prieš pradedant kitą. Pereiti prie asinchroninio gali būti nemalonu, nes tam reikia išmokti ne tik naujos sintaksės, bet ir naujų mąstymo apie savo kodą būdų.

Šiame straipsnyje mes ištirsime, kaip esamą, sinchronišką programą galima paversti asinchronine. Tai apima ne tik funkcijų dekoravimą naudojant asinchroninę sintaksę; taip pat reikia kitaip pagalvoti, kaip veikia mūsų programa, ir nuspręsti, ar asinchronija yra net gera metafora tam, ką ji daro.

[Taip pat: Sužinokite „Python“ patarimus ir gudrybes iš Serdaro Yegulalpio „Smart Python“ vaizdo įrašų]

Kada naudoti „Python“ asinchronizavimą

„Python“ programa geriausiai tinka asinchronizuoti, kai ji turi šias savybes:

  • Tai bandoma padaryti tai, kas dažniausiai yra susieta su įvestimi / išvestimi, arba laukti, kol bus baigtas koks nors išorinis procesas, pavyzdžiui, ilgai veikiantis tinklo skaitymas.
  • Tai bando atlikti vieną ar kelias iš šių užduočių vienu metu, galbūt taip pat tvarkant vartotojo sąveiką.
  • Aptariamos užduotys nėra sudėtingos skaičiavimais.

„Python“ programa, naudojanti siūlų gavimą, paprastai yra tinkama kandidatė naudoti „asinchroninį“. „Python“ gijos yra bendradarbiaujančios; jie vienas kitam pasiduoda kaip reikia. Async „Python“ užduotys veikia taip pat. Be to, async siūlo tam tikrus pranašumus, palyginti su gijomis:

  • asinchroninis/laukti sintaksė leidžia lengvai nustatyti asinchronines programos dalis. Priešingai, dažnai sunku iš pirmo žvilgsnio pasakyti, kokios programos dalys vykdomos gijoje.
  • Kadangi asinchroninės užduotys turi tą pačią giją, visus duomenis, prie kurių jie prisijungia, automatiškai valdo GIL („Python“ gimtoji prieigos prie objektų sinchronizavimo priemonė). Siūlai dažnai reikalingi sudėtingi sinchronizavimo mechanizmai.
  • Async užduotis lengviau valdyti ir atšaukti nei gijas.

Async naudojimas yra ne rekomenduojama, jei jūsų „Python“ programa turi šias charakteristikas:

  • Užduotys turi dideles skaičiavimo išlaidas, pvz., Jos atlieka daug skaičių. Geriausia atlikti sunkų skaičiavimą daugiaprocesinis, leidžiančią skirti visumą techninė įranga gija prie kiekvienos užduoties.
  • Užduotims nėra naudos persipynus. Jei kiekviena užduotis priklauso nuo paskutinės, nėra prasmės priversti jas vykdyti asinchroniškai. Tai pasakė, jei programa apimarinkiniai serijinių užduočių, kiekvieną rinkinį galite paleisti asinchroniškai.

1 veiksmas: nustatykite sinchronines ir asinchronines programos dalis

„Python“ asinchroninį kodą turi paleisti sinchroninės „Python“ programos dalys ir jis turi jį valdyti. Tuo tikslu pirmoji jūsų užduotis konvertuojant programą į asinchroninę yra nubrėžti liniją tarp kodo sinchronizavimo ir asinchronizavimo dalių.

Ankstesniame straipsnyje apie asinchronizavimą kaip paprastą pavyzdį naudojome žiniatinklio grandiklio programą. Asinchroninės kodo dalys yra įprastos, atidarančios tinklo ryšius ir skaitančios iš svetainės - viskas, ką norite persipinti. Tačiau programos dalis, kuri visa tai atmeta, nėra asinchroninė; ji paleidžia asinchronines užduotis ir grakščiai jas uždaro, kai jos baigiamos.

Taip pat svarbu atskirti visus potencialiaiblokavimo operacija nuo asinchroninio ir laikykite jį programos sinchronizavimo dalyje. Pavyzdžiui, skaitant vartotojo įvestį iš konsolės, blokuojama viskas, įskaitant asinchroninio įvykio ciklą. Todėl jūs norite tvarkyti vartotojo įvestį prieš paleidžiant asinchronines užduotis arba jas baigus. (Tai yra galima asinchroniškai valdyti vartotojo įvestį naudojant daugiaprocesorinį procesą arba sriegį, tačiau tai yra pažangus pratimas, kurio čia nenagrinėsime.)

Keletas blokavimo operacijų pavyzdžių:

  • Pulto įvestis (kaip ką tik aprašėme).
  • Užduotys, susijusios su dideliu procesoriaus naudojimu.
  • Naudojant laikas.miega priversti padaryti pauzę. Atminkite, kad galite miegoti asinchroninės funkcijos viduje naudodami asyncio.miega kaip pakaitalą laikas.miega.

2 žingsnis: konvertuokite atitinkamas sinchronizavimo funkcijas į asinchronines funkcijas

Kai žinosite, kurios programos dalys bus vykdomos asinchroniškai, galite jas suskaidyti į funkcijas (jei dar to nepadarėte) ir paversti asinchroninėmis funkcijomis su asinchroninis raktinis žodis. Tada turėsite pridėti kodą į sinchroninę programos dalį, kad paleistumėte asinchroninį kodą ir prireikus surinktumėte jo rezultatus.

Pastaba: norėsite patikrinti kiekvienos funkcijos, kurią padarėte asinchroninę, skambučių grandinę ir įsitikinti, kad jos nekviečia potencialiai ilgai trunkančios ar blokuojančios operacijos. „Async“ funkcijos gali tiesiogiai iškviesti sinchronizavimo funkcijas, o jei ta sinchronizavimo funkcija blokuojasi, tai daro ir ją iškviečianti „asinchroninė“ funkcija.

Pažvelkime į supaprastintą pavyzdį, kaip gali veikti sinchronizavimo į asinchroninę konversiją. Čia yra mūsų programa „prieš“:

def a_function (): # kai kurie su async suderinami veiksmai, kurie užtrunka, def another_function (): # kažkokia sinchronizavimo funkcija, bet ne blokuojanti vieną def do_stuff (): a_function () another_function () def main (): už _ diapazone (3): do_stuff () main () 

Jei norime trijų atvejų do_ stuff norėdami paleisti kaip asinchronines užduotis, turime pasukti do_ stuff (ir galbūt viską, ką paliečia) į asinchroninį kodą. Čia yra pirmasis konversijos praėjimas:

importuoti asyncio async def a_function (): # kažkoks su async suderinamas veiksmas, kuris užtrunka, def another_function (): # kai kuri sinchronizavimo funkcija, bet ne blokuojanti async def do_stuff (): laukti a_function () another_function () async def main ( ): Užduotys = [] už _ diapazone (3): užduotys.applanas (asyncio.create_task (do_stuff ())) laukia asyncio.gather (užduotys) asyncio.run (main ()) 

Atkreipkite dėmesį į pakeitimus, kuriuos atlikomepagrindinis. Dabar pagrindinis naudoja asyncio paleisti kiekvieną do_ stuff kaip kartu atliekama užduotis, tada laukia rezultatų (asyncio.gather). Mes taip pat atsivertėme a_funkcija į asinchroninę funkciją, nes norime visų a_funkcija paleisti greta ir kartu su visomis kitomis funkcijomis, kurioms reikalingas asinchroninis elgesys.

Jei norėtume žengti dar vieną žingsnį, taip pat galėtume atsiversti kita_funkcija į asinchronizuoti:

async def another_function (): # kai kuri sinchronizavimo funkcija, bet ne blokuojanti async def do_stuff (): lauki a_function () lauki another_function () 

Tačiau darantkita_funkcija asinchroninis būtų perdėtas, nes (kaip jau pažymėjome) jis nedaro nieko, kas blokuotų mūsų programos eigą. Be to, jei yra sinchroninių mūsų programos daliųkita_funkcija, mes taip pat turėtume juos konvertuoti į asinchroninius, o tai gali padaryti mūsų programą sudėtingesnę nei turėtų būti.

3 žingsnis: kruopščiai išbandykite „Python“ asinchroninę programą

Bet kurią asinchroniškai konvertuotą programą reikia išbandyti prieš pradedant gaminti, kad ji veiktų taip, kaip tikėtasi.

Jei jūsų programa yra nedidelio dydžio - tarkime, maždaug pora dešimčių eilučių - ir jai nereikia viso testų rinkinio, tada neturėtų būti sunku patikrinti, ar ji veikia taip, kaip numatyta. Tai reiškia, kad jei konvertuojate programą į asinchronizavimą kaip didesnio projekto dalį, kur testų rinkinys yra standartinis įrenginys, tikslinga rašyti tiek asinchroninių, tiek sinchronizuojamų komponentų bandymus.

Abi pagrindinės „Python“ testavimo sistemos dabar turi tam tikrą asinchroninį palaikymą. Savo „Python“vieningiausias sistema apima bandymo atvejo objektus asinchroninėms funkcijoms ir pytest pasiūlymaipytest-asyncio tiems patiems tikslams.

Galiausiai, rašydami asinchroninių komponentų testus, turite laikyti jų asinchroniškumą kaip testų sąlygą. Pavyzdžiui, nėra jokios garantijos, kad asinchroniniai darbai bus baigti tokia tvarka, kokia jie buvo pateikti. Pirmasis gali pasirodyti paskutinis, o kai kurie gali būti visiškai nebaigti. Atliekant bet kokius asinchroninės funkcijos bandymus reikia atsižvelgti į šias galimybes.

Kaip padaryti daugiau su „Python“

  • Pradėkite naudoti „Python“ asinchronizavimą
  • Kaip naudoti „asyncio“ Python
  • Kaip naudoti „PyInstaller“, norint sukurti „Python“ vykdomuosius failus
  • „Cython“ pamoka: kaip pagreitinti „Python“
  • Kaip įdiegti „Python“ išmaniuoju būdu
  • Kaip valdyti „Python“ projektus naudojant „Poeziją“
  • Kaip valdyti „Python“ projektus naudojant „Pipenv“
  • „Virtualenv“ ir „venv“: paaiškintos „Python“ virtualios aplinkos
  • „Python virtualenv“ ir „venv do and donts“
  • Paaiškinta „Python“ sriegimas ir antriniai procesai
  • Kaip naudotis „Python“ derintuvu
  • Kaip naudoti „Timeit“, kad būtų galima nustatyti „Python“ kodą
  • Kaip naudoti „cProfile“ „Python“ kodui nustatyti
  • Kaip konvertuoti „Python“ į „JavaScript“ (ir dar kartą)
$config[zx-auto] not found$config[zx-overlay] not found