Pourquoi Async/Await en Python ?
L'utilisation d'Async/Await en Python est essentielle pour augmenter l'efficacité et la performance de vos applications, surtout lorsqu'elles manipulent des opérations asynchrones comme les requêtes réseau, la lecture/écriture sur le disque dur ou les interactions avec une base de données. Ces opérations peuvent prendre du temps, mais en utilisant Async/Await, vous pouvez permettre à votre application de continuer à traiter d'autres tâches pendant que ces opérations sont en cours.
Un cas concret est un site web qui utilise des requêtes réseau pour récupérer des données. Sans Async/Await, le traitement serait synchrone, ce qui signifie que l'application serait bloquée jusqu'à la réception de toutes les données. Avec Async/Await, chaque requête peut être traitée de manière asynchrone, permettant à l'application de continuer à répondre aux autres requêtes.
Prerequis
- Connaissances en Python
- Compréhension des boucles
foretwhile - Connaissance des structures de données comme les listes et les dictionnaires
- Familiarité avec la gestion des exceptions en Python
- Installation de Python (version 3.5 ou plus tard recommandée)
Concepts fondamentaux
1. Les Fonctions Asynchrones
Une fonction asynchrone est une fonction qui peut être exécutée de manière non bloquante grâce à l'utilisation d'Async/Await.
async def fetch_data():
# Simulate a network request
await asyncio.sleep(1)
return {"data": "Example data"}
2. L'exécution Asynchrone
Pour exécuter une fonction asynchrone, vous devez l'encapsuler dans un événement boucle (event loop) et utiliser la méthode run().
import asyncio
##
async def main():
data = await fetch_data()
print(data)
##
asyncio.run(main())
3. Await
L'opérateur await est utilisé pour attendre la résolution d'une promesse (Promise) ou d'une autre fonction asynchrone.
import asyncio
##
async def fetch_data():
# Simulate a network request
await asyncio.sleep(1)
return {"data": "Example data"}
##
async def main():
response = await fetch_data()
print(response)
##
asyncio.run(main())
4. La Gestion des Exceptions
La gestion des exceptions dans les fonctions asynchrones est similaire à celle dans les fonctions synchrones.
import asyncio
##
async def fetch_data():
await asyncio.sleep(1)
raise ValueError("Failed to fetch data")
##
async def main():
try:
response = await fetch_data()
print(response)
except ValueError as e:
print(f"Error: {e}")
##
asyncio.run(main())
Mise en pratique : projet fil rouge
Nous allons construire un mini-projet complet qui utilise Async/Await pour récupérer des données à partir d'une API et les afficher.
Étape 1 : Création du Projet
Créez un nouveau répertoire pour votre projet et initialisez un environnement virtuel.
mkdir async_api_project
cd async_api_project
python -m venv venv
source venv/bin/activate # Sous Windows utilisez `venv\Scripts\activate`
Étape 2 : Installation des Dépendances
Installez les dépendances nécessaires.
pip install aiohttp
Étape 3 : Création du Code Asynchrone
Créez un fichier main.py et ajoutez le code suivant :
import asyncio
import aiohttp
##
async def fetch_data(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.json()
##
async def main():
url = "https://jsonplaceholder.typicode.com/posts"
data = await fetch_data(url)
print(data)
##
if __name__ == "__main__":
asyncio.run(main())
Étape 4 : Exécution du Projet
Exécutez le script avec la commande suivante :
python main.py
Erreurs Frequentes et Debugging
Erreur 1 : RuntimeError: Event loop is closed
Cela se produit lorsque vous essayez d'exécuter une fonction asynchrone après que l'événement boucle a été fermée.
Code incorrect :
import asyncio
async def fetch_data():
await asyncio.sleep(1)
return {"data": "Example data"}
##
asyncio.run(fetch_data())
Code correct :
import asyncio
async def fetch_data():
await asyncio.sleep(1)
return {"data": "Example data"}
##
async def main():
data = await fetch_data()
print(data)
##
if __name__ == "__main__":
asyncio.run(main())
Erreur 2 : TypeError: 'NoneType' object is not callable
Cela se produit lorsque vous essayez d'appeler une fonction qui n'est pas définie ou qui est définie comme None.
Code incorrect :
import asyncio
async def fetch_data():
await asyncio.sleep(1)
return {"data": "Example data"}
##
async def main():
data = await fetch_data()
print(data)
##
if __name__ == "__main__":
asyncio.run(main())
Code correct :
import asyncio
async def fetch_data():
await asyncio.sleep(1)
return {"data": "Example data"}
##
async def main():
data = await fetch_data()
print(data)
##
if __name__ == "__main__":
asyncio.run(main())
Erreur 3 : TimeoutError: Cannot connect to host jsonplaceholder.typicode.com:80 [Connect call failed]
Cela se produit lorsque votre application ne peut pas se connecter à l'hôte spécifié.
Code incorrect :
import asyncio
import aiohttp
async def fetch_data(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.json()
##
async def main():
url = "https://jsonplaceholder.typicode.com/posts"
data = await fetch_data(url)
print(data)
##
if __name__ == "__main__":
asyncio.run(main())
Code correct :
import asyncio
import aiohttp
async def fetch_data(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.json()
##
async def main():
url = "https://jsonplaceholder.typicode.com/posts"
data = await fetch_data(url)
print(data)
##
if __name__ == "__main__":
asyncio.run(main())
Pour aller plus loin
1. La Concurrency avec Async/Await
Apprenez à utiliser la concurrence avec Async/Await pour exécuter plusieurs tâches en même temps.
2. Les Libraries Asynchrones Populaires
Explorez les principales bibliothèques asynchrones populaires en Python comme aiohttp, aioredis, et asyncpg.
3. Les Cas d'Usage Avancés
Découvrez les cas d'utilisation avancés de Async/Await, tels que la gestion des fichiers asynchrones et la création de CLI tools avec Async/Await.
Défi Pratique
Créez un script qui utilise Async/Await pour récupérer des données d'une API de weather et affiche la météo pour une ville spécifique. Utilisez aiohttp pour faire les requêtes réseau.
import asyncio
import aiohttp
async def fetch_weather(city):
url = f"https://api.openweathermap.org/data/2.5/weather?q={city}&appid=YOUR_API_KEY"
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.json()
##
async def main():
city = "Paris"
weather_data = await fetch_weather(city)
print(f"Weather in {city}: {weather_data['weather'][0]['description']}")
##
if __name__ == "__main__":
asyncio.run(main())
N'oubliez pas de remplacer YOUR_API_KEY par votre clé API OpenWeatherMap.
Ce tutoriel approfondi devrait vous donner une bonne compréhension de la manière dont Async/Await peut être utilisé en Python pour optimiser les applications qui traitent des opérations asynchrones.