Obiective:
- Introducerea conceptului de co-rutine și funcții asincrone
- Folosirea cuvântului cheie
async defpentru a crea funcții asincrone - Utilizarea cuvântului cheie
awaitpentru a apela alte funcții asincrone - Crearea de co-rutine și gestionarea lor cu
asyncio - Exemple practice și aplicații ale co-rutinelor și funcțiilor asincrone
Introducere: Co-rutine și funcții asincrone
Co-rutinele sunt un mecanism de programare care permite ca mai multe funcții să ruleze concurent, dar să se execute într-un singur fir de execuție. Aceasta înseamnă că funcțiile pot să își „pauzeze” execuția, să permită altor funcții să ruleze și să reia execuția ulterior de unde au rămas. Funcțiile asincrone sunt un mod de a crea co-rutine în Python.
Python 3.5 a introdus cuvântul cheie async def, care permite crearea de funcții asincrone. Funcțiile asincrone pot fi apelate cu ajutorul cuvântului cheie await. Atunci când o funcție asincronă este apelată, ea returnează un obiect co-rutină, care poate fi gestionat cu ajutorul bibliotecii asyncio.
Crearea de funcții asincrone cu async def și await
Putem crea o funcție asincronă folosind cuvântul cheie async def. În interiorul unei funcții asincrone, putem folosi cuvântul cheie await pentru a apela alte funcții asincrone. Să luăm un exemplu simplu:
import asyncio
async def salut(nume):
print(f'Salut {nume}!')
await asyncio.sleep(1)
print(f'La revedere {nume}!')
async def main():
await salut('Alice')
await salut('Bob')
asyncio.run(main())
În acest exemplu, avem o funcție asincronă salut, care afișează un mesaj, așteaptă un timp stabilit de asyncio.sleep, și apoi afișează un alt mesaj. Funcția main este, de asemenea, asincronă și apelează funcția salut pentru mai multe nume folosind await.
Pentru a rula co-rutina principală, folosim funcția asyncio.run(main()).
Crearea de co-rutine și gestionarea lor cu asyncio
Pentru a rula mai multe co-rutine în paralel, putem folosi funcția asyncio.gather. Aceasta combină mai multe co-rutine și le rulează toate în paralel:
import asyncio
async def salut(nume):
print(f'Salut {nume}!')
await asyncio.sleep(1)
print(f'La revedere {nume}!')
async def main():
corutine = [salut('Alice'), salut('Bob'), salut('Carol')]
await asyncio.gather(*corutine)
asyncio.run(main())
În acest exemplu, funcția main creează o listă de co-rutine folosind funcția salut și apoi așteaptă ca toate să fie finalizate folosind asyncio.gather.
Exemple practice și aplicații ale co-rutinelor și funcțiilor asincrone
1. Descărcarea de fișiere în paralel
Co-rutinele și funcțiile asincrone sunt utile în situații în care avem operații I/O care pot fi efectuate în paralel. De exemplu, să presupunem că dorim să descărcăm mai multe fișiere de pe internet. În loc să descărcăm fiecare fișier pe rând, putem folosi co-rutine pentru a descărca fișierele în paralel:
import aiohttp
import asyncio
async def descarca_fisier(url, nume_fisier):
async with aiohttp.ClientSession() as sesiune:
async with sesiune.get(url) as raspuns:
with open(nume_fisier, 'wb') as fisier:
while True:
chunk = await raspuns.content.read(1024)
if not chunk:
break
fisier.write(chunk)
print(f'Fișierul {nume_fisier} a fost descărcat.')
async def main():
url_fisiere = [
('https://example.com/fisier1.txt', 'fisier1.txt'),
('https://example.com/fisier2.txt', 'fisier2.txt'),
('https://example.com/fisier3.txt', 'fisier3.txt'),
]
corutine = [descarca_fisier(url, nume_fisier) for url, nume_fisier in url_fisiere]
await asyncio.gather(*corutine)
asyncio.run(main())
2. Interogarea unei baze de date în paralel
De asemenea, putem folosi co-rutine pentru a interoga o bază de date în paralel:
import aiomysql
import asyncio
async def interogare_baza_de_date(index):
pool = await aiomysql.create_pool(host='127.0.0.1', port=3306, user='root', password='my_secret', db='test', loop=loop)
async with pool.acquire() as conn:
async with conn.cursor() as cursor:
await cursor.execute("SELECT * FROM utilizatori WHERE index = %s", (index,))
rezultat = await cursor.fetchone()
print(rezultat)
async def main():
indici = [1, 2, 3, 4, 5]
corutine = [interogare_baza_de_date(index) for index in indici]
await asyncio.gather(*corutine)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Acesta este doar începutul a ceea ce se poate face cu co-rutine și funcții asincrone în Python. În viitor, puteți să explorați biblioteca asyncio și alte biblioteci asincrone care oferă funcționalități suplimentare și extinderea programelor asincrone.