Les gestionnaires de contexte asynchrones en Python changent la donne pour la gestion des ressources dans les applications concurrentes. Ils ressemblent à des gestionnaires de contexte classiques, mais avec une particularité : ils fonctionnent de manière transparente avec du code asynchrone.
Commençons par les bases. Pour créer un gestionnaire de contexte asynchrone, nous devons implémenter deux méthodes spéciales : __aenter__ et __aexit__. Ce sont les versions asynchrones de __enter__ et __exit__ que nous utilisons dans les gestionnaires de contexte classiques.
Voici un exemple simple :
class AsyncResource: async def __aenter__(self): print("Acquiring resource") await asyncio.sleep(1) # Simulating async acquisition return self async def __aexit__(self, exc_type, exc_value, traceback): print("Releasing resource") await asyncio.sleep(1) # Simulating async release async def main(): async with AsyncResource() as resource: print("Using resource") asyncio.run(main())
Dans cet exemple, nous simulons l'acquisition et la libération asynchrones d'une ressource. L'instruction async with se charge d'appeler __aenter__ et __aexit__ aux bons moments.
Parlons maintenant des raisons pour lesquelles les gestionnaires de contexte asynchrones sont si utiles. Ils sont parfaits pour gérer les ressources qui nécessitent des opérations asynchrones, comme les connexions à des bases de données, les sockets réseau ou les gestionnaires de fichiers, de manière non bloquante.
Prenons par exemple les connexions à des bases de données. Nous pouvons créer un gestionnaire de contexte asynchrone qui gère un pool de connexions :
import asyncpg class DatabasePool: def __init__(self, dsn): self.dsn = dsn self.pool = None async def __aenter__(self): self.pool = await asyncpg.create_pool(self.dsn) return self.pool async def __aexit__(self, exc_type, exc_value, traceback): await self.pool.close() async def main(): async with DatabasePool('postgresql://user:password@localhost/db') as pool: async with pool.acquire() as conn: result = await conn.fetch('SELECT * FROM users') print(result) asyncio.run(main())
Cette configuration garantit que nous gérons efficacement nos connexions à la base de données. La piscine est créée lorsqu'on entre dans le contexte et correctement fermée lorsqu'on en sort.
La gestion des erreurs dans les gestionnaires de contexte asynchrones est similaire aux gestionnaires classiques. La méthode __aexit__ reçoit des informations d'exception si une erreur se produit dans le contexte. Nous pouvons gérer ces erreurs ou les laisser se propager :
class ErrorHandlingResource: async def __aenter__(self): return self async def __aexit__(self, exc_type, exc_value, traceback): if exc_type is ValueError: print("Caught ValueError, suppressing") return True # Suppress the exception return False # Let other exceptions propagate async def main(): async with ErrorHandlingResource(): raise ValueError("Oops!") print("This will be printed") async with ErrorHandlingResource(): raise RuntimeError("Unhandled!") print("This won't be printed") asyncio.run(main())
Dans cet exemple, nous supprimons ValueError mais autorisons la propagation d'autres exceptions.
Les gestionnaires de contexte asynchrones sont également parfaits pour implémenter des verrous distribués. Voici un exemple simple utilisant Redis :
import aioredis class DistributedLock: def __init__(self, redis, lock_name, expire=10): self.redis = redis self.lock_name = lock_name self.expire = expire async def __aenter__(self): while True: locked = await self.redis.set(self.lock_name, "1", expire=self.expire, nx=True) if locked: return self await asyncio.sleep(0.1) async def __aexit__(self, exc_type, exc_value, traceback): await self.redis.delete(self.lock_name) async def main(): redis = await aioredis.create_redis_pool('redis://localhost') async with DistributedLock(redis, "my_lock"): print("Critical section") await redis.close() asyncio.run(main())
Ce verrou garantit qu'un seul processus peut exécuter la section critique à la fois, même sur plusieurs machines.
Nous pouvons également utiliser des gestionnaires de contexte asynchrones pour les étendues de transaction :
class AsyncTransaction: def __init__(self, conn): self.conn = conn async def __aenter__(self): await self.conn.execute('BEGIN') return self async def __aexit__(self, exc_type, exc_value, traceback): if exc_type is None: await self.conn.execute('COMMIT') else: await self.conn.execute('ROLLBACK') async def transfer_funds(from_account, to_account, amount): async with AsyncTransaction(conn): await conn.execute('UPDATE accounts SET balance = balance - WHERE id = ', amount, from_account) await conn.execute('UPDATE accounts SET balance = balance + WHERE id = ', amount, to_account)
Cette configuration garantit que nos transactions de base de données sont toujours correctement validées ou annulées, même en cas d'exceptions.
Les gestionnaires de contexte asynchrone peuvent être combinés avec d'autres primitives asynchrones pour des modèles encore plus puissants. Par exemple, nous pouvons les utiliser avec asyncio.gather pour la gestion parallèle des ressources :
async def process_data(data): async with ResourceManager() as rm: results = await asyncio.gather( rm.process(data[0]), rm.process(data[1]), rm.process(data[2]) ) return results
Cela nous permet de traiter plusieurs éléments de données en parallèle tout en assurant une bonne gestion des ressources.
En conclusion, les gestionnaires de contexte asynchrone sont un outil puissant pour gérer les ressources dans le code Python asynchrone. Ils offrent un moyen propre et intuitif de gérer la configuration et le démontage asynchrones, la gestion des erreurs et le nettoyage des ressources. En maîtrisant les gestionnaires de contexte asynchrone, vous serez bien équipé pour créer des applications Python robustes et évolutives, capables de gérer facilement des flux de travail complexes et simultanés.
N'oubliez pas de consulter nos créations :
Centre des investisseurs | Vie intelligente | Époques & Échos | Mystères déroutants | Hindutva | Développeur Élite | Écoles JS
Tech Koala Insights | Epoques & Echos Monde | Support Central des Investisseurs | Mystères déroutants Medium | Sciences & Epoques Medium | Hindutva moderne
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!