Programarea asincronă în Python devine din ce în ce mai populare. În acest scop, există mai multe biblioteci diferite. Cele mai populare dintre ele - Asyncio. care este o bibliotecă standard Python 3.4. În acest articol veți afla ce programare asincron și diferențele dintre diversele biblioteci care implementează asincron în Python.
la rândul său,
În fiecare linie de cod program alternativ efectuat. De exemplu, dacă aveți o linie de cod care cere ceva de la server, aceasta înseamnă că programul nu face nimic în timp ce așteaptă un răspuns. În unele cazuri, este permisă, dar în multe - nu. O soluție la această problemă sunt fluxurile (firele).
Curente permite programul pentru a efectua o serie de sarcini simultan. Desigur, firele au o serie de dezavantaje. Programele multithreaded sunt mai complexe și tind să fie mai predispuse la erori. Acestea includ astfel de probleme: starea rasei (starea de rasă), reciprocă (de blocaj) și (livelock) de blocare activă, epuizarea resurselor (foame de resurse).
comutare context
Deși programarea asincron, și vă permite să ocolească zonele cu probleme de fluxuri, a fost proiectat pentru un scop cu totul diferit - pentru a comuta contextul procesorului. Când aveți mai multe fire, fiecare nucleu poate rula doar un singur fir la un moment dat. Pentru toate firele / procesele pot partaja resursele, procesorul efectuează adesea o schimbare de context. Pentru a face mai ușor, procesorul cu o frecvență arbitrară păstrează toate fluxul de informații contextuale și trece la un alt fir.
Asincronă de programare - un flux de procesare spațiu software / utilizator, în cazul în care cererea, nu procesorul, controlează comutarea debitului și a contextului. În contextul de programare, asincron comută numai la punctele de comutare predeterminate, în loc de intervalele descrise CPU.
secretar eficient
Curente - o perioada de cinci secretari, fiecare dintre care are o singură sarcină, dar numai una dintre ele este permis să opereze într-un anumit interval de timp. Pentru secretare a lucrat în modul de streaming, aveți nevoie de un dispozitiv care monitorizează activitatea lor, dar nu înțelege problemele în sine. Deoarece dispozitivul nu înțelege natura sarcinilor pe care le-ar schimba în mod constant între cinci secretari, chiar dacă trei dintre ele sunt ședinței în jurul valorii de a face nimic. Aproximativ 57% (puțin mai mică decât 3/5) de comutare context, ar fi fost în zadar. În ciuda faptului că comutatorul de context, procesorul este incredibil de rapid, este încă nevoie de timp și resurse CPU.
fire verzi
Dupa cum se poate vedea, Gevent API-interfață arată la fel ca fluxuri. Cu toate acestea, în spatele scenei se folosește (să aibă corutine) să aibă corutine, mai degrabă decât fluxuri, și le execută într-un ciclu de evenimente (bucla eveniment) pentru plasarea în coadă. Acest lucru înseamnă că veți obține fluxul de beneficii fara a intelege aibă corutine, dar nu scapa de problemele asociate cu fluxul. Gevent - o bibliotecă bună, dar numai pentru cei care înțeleg cum funcționează fire.
Să ne uităm la unele aspecte ale programării asincrone. Unul dintre aceste aspecte - acest ciclu de evenimente. ciclu de evenimente - totul evenimente / sarcini și o buclă care se extinde de la coada de așteptare și le execută. Aceste sarcini sunt numite să aibă corutine. Ele sunt un mic set de comenzi care conțin, printre altele, instrucțiuni cu privire la ce evenimente, dacă este necesar, trebuie să fie returnat la coada.
Funcția de apel invers (callback)
În Python, o mulțime de biblioteci pentru programare asincron, cele mai populare sunt Tornado, Asyncio și Gevent. Să vedem cum Tornado. Acesta folosește un stil de apel invers (callback) pentru rețeaua asincron IO. Sună înapoi - o caracteristică, ceea ce înseamnă: „De îndată ce acest lucru se face, urmați această funcție.“ Cu alte cuvinte, apelați biroul de ajutor și lăsați numărul, astfel încât atunci când acesta va fi disponibil, chemat înapoi, în loc să aștepte răspunsul lor.
Să vedem cum se face la fel ca mai sus, folosind Tornado:
Tornado. ioloop. IOLoop. exemplu (). start ()
În exemplul pe care se poate observa că primele verificări funcționale linie handle_response pentru erori. Acest lucru este necesar, deoarece nu se poate ocupa de excepție. În cazul în care o excepție a fost creată, aceasta nu va fi practicată în codul buclei evenimentului. Când fetch este executat, acesta pornește HTTP-cerere, și apoi procesează răspunsul la bucla eveniment. Până în momentul în care apare o eroare, stiva de apel va conține numai ciclul de evenimente și funcția curentă, în timp ce în altă parte în acest cod nu funcționează excludere. Astfel, orice excluderi create în funcție de apel invers, întrerupe ciclul de evenimente și executarea programului de oprire. Prin urmare, toate erorile ar trebui să fie menționate ca obiecte, nu sunt tratate ca excepții. Acest lucru înseamnă că, dacă nu ați verificat pentru erori, atunci acestea nu vor fi procesate.
O altă problemă cu callbacks constă în faptul că, în programarea asincron, singura modalitate de a evita blocajele - acest apel invers. Acest lucru poate duce la lanț foarte lung: apel invers, după un apel invers, după un apel invers. Deoarece pierdut accesul la stiva, și variabile, vă va duce în cele din urmă obiecte mari în toate callback dvs., dar dacă utilizați API, interfețe terțe părți, nu vă pot spune nimic pentru a apela înapoi, dacă el nu poate accepta. Ea devine, de asemenea, o problemă, deoarece fiecare apel invers funcții ca un flux. De exemplu, doriți să apelați trei API-interfață și așteptați până când toate trei se vor întoarce rezultatul să fie generalizate. În Gevent puteți face acest lucru, dar nu cu callback. Vei avea puține pokoldovat, stocarea rezultat într-o variabilă globală și de verificare în apel invers, dacă rezultatul final.
Dacă doriți pentru a preveni blocarea IO, trebuie să utilizați fie fluxuri sau asincronă. În Python să alegeți între firele verzi și callback asincrone. Iată câteva dintre caracteristicile lor:
fire verzi
- Fluxurile sunt gestionate la nivel de aplicație, mai degrabă decât hardware-ul;
- Acesta include toate problemele de streaming de programare.
apel invers
- să aibă corutine invizibil pentru programator;
- Reapelări limitează utilizarea excepțiilor;
- callback sunt dificil de depanare.
Cum de a rezolva aceste probleme?
Până la Python 3.3 fluxuri verzi și de apel invers sunt soluții optime. Pentru a depasi aceste decizii au nevoie de sprijin la nivelul limbii. Python trebuie să execute într-un fel, parțial o metodă pentru a opri execuția, menținând în același timp obiectele stiva excepții. Dacă sunteți familiarizat cu conceptele Python, ați înțeles ce am ajunge la generator. Generatoarele permit o funcție pentru a returna o listă cu un singur element la un moment dat, oprirea executării până în momentul în care se solicită elementul următor. Problema cu generatoare este că acestea sunt complet dependente de funcția, numindu-l. Cu alte cuvinte, generatorul nu poate provoca generatorul. Cel puțin era atâta timp cât PEP 380 nu produce de sintaxă adăugată. care permite generatorul pentru a obține rezultatul unui alt generator de. Deși asincron și nu este scopul principal al generatoarelor, ele conțin toate caracteristicile pentru a fi destul de util. Generator sprijină stiva și poate crea excepții. Dacă ați scris un ciclu de evenimente, care ar fi generatorul, v-ar fi fost o mare bibliotecă asincron. Aceasta este exact ceea ce a fost creat Asyncio bibliotecă.
Aproximativ Trans. Exemplele folosesc aiohttp 1.3.5. Cea mai recentă versiune a bibliotecii o sintaxă diferită.
Mai multe caracteristici care ar trebui să fie remarcat:
- Eroare transmise corect în stivă;
- Puteți returna un obiect, dacă este necesar;
- Puteți rula toate să aibă corutine;
- Nu există callback;
- linia 10 nu va fi executat, atâta timp cât linia 9 va fi pus în aplicare pe deplin.
Singura problemă este că obiectul arata ca un generator, iar acest lucru poate cauza probleme, în cazul în care, de fapt, era generatorul.
Async și așteaptă
Asyncio bibliotecă destul de puternic, astfel încât Python a decis să-l biblioteca standard de a face. Sintaxa a adăugat, de asemenea, asincronă de cuvinte cheie. Tag-uri sunt concepute pentru a spori vizibilitatea codului asincron. Deci, acum metodele nu sunt confundate cu generatoarele. Async cuvinte cheie este să DEF. pentru a arăta că metoda este asincron. Cuvinte cheie așteaptă spectacole pe care vă așteptați pentru a finaliza să aibă corutine. Iată același exemplu, dar cu async cuvinte cheie / așteaptă:
Programul constă într-o metodă asincronă. În timpul rulării, se returnează coroutine, care apoi este în așteptare.
concluzie
bibliotecă asincron excelent construit în Python. Să ne amintim încă o dată fluxurile de probleme și a vedea dacă acestea sunt acum rezolvate:
- CPU de comutare de context. Asyncio este asincron și folosește o buclă de eveniment. Acesta vă permite să comutați contextul programului;
- condiție cursă: ca Asyncio rulează numai un singur coroutine și au trecut numai la punctele pe care le definiți, codul nu este supus problema fluxurilor de rasă;
- Reciprocă / blocare activă: acum, deoarece nu există nici un flux de cursa, nu va trebui să vă faceți griji cu privire la încuietori. Deși impas poate avea loc în continuare într-o situație în care două să aibă corutine apel reciproc, astfel încât este puțin probabil că va trebui să încerce să facă acest lucru;
- epuizarea resurselor: din moment ce rulează într-un să aibă corutine singur fir și nu necesită memorie suplimentară, devine mult mai dificil de a alerga afară de resurse. Cu toate acestea Asyncio au un bazin de „artiști» (executori), care, în esență, este un bazin de fire. Dacă executați prea multe procese în piscina de interpreți, s-ar putea fi încă se confruntă cu o lipsă de resurse.
În ciuda faptului că Asyncio destul de bine, ea are, de asemenea, problemele sale. În primul rând, Asyncio a fost adăugat recent în Python. Există unele deficiențe care încă nu au corectat. În al doilea rând, atunci când utilizați asincron, ceea ce înseamnă că toate codul dvs. trebuie să fie asincron. Acest lucru se datorează faptului că punerea în aplicare a funcțiilor asincrone poate dura prea mult timp, blocând astfel bucla eveniment.
Există mai multe opțiuni pentru programarea în Python asincron. Puteți folosi fire de verde, callback sau să aibă corutine. Deși o mulțime de opțiuni, cele mai bune dintre ele - Asyncio. Dacă utilizați Python 3.5, veți utiliza mai bine această bibliotecă, deoarece este construit în miez de piton.