# Asyncio Best Practices and Common Pitfalls ## Writing Better Asyncio Code: Dos and Don'ts Python's asyncio library is powerful but comes with its own set of conventions and potential pitfalls. Let's explore the best practices to follow and common mistakes to avoid. ### Best Practices #### 1. Use `asyncio.run()` as Your Main Entry Point Always use `asyncio.run()` to start your asyncio programs: ```python # Good practice async def main(): # Your async code here pass if __name__ == "__main__": asyncio.run(main()) ``` This function properly sets up and tears down the event loop, and handles cleanup when exceptions occur. #### 2. Prefer Async Context Managers When available, use async context managers (`async with`) for proper resource management: ```python # Good practice async with aiohttp.ClientSession() as session: async with session.get(url) as response: data = await response.text() ``` #### 3. Always Await Coroutines One of the most common mistakes is forgetting to await coroutines. Always await them: ```python # Bad - coroutine is created but never executed fetch_data(url) # Good - coroutine is awaited and executed await fetch_data(url) # Also good - coroutine is executed via asyncio.run() asyncio.run(fetch_data(url)) ``` #### 4. Handle Cancellation Gracefully Always catch `CancelledError` and clean up resources in tasks that might be cancelled: ```python async def cancellable_task(): try: # Your task code while True: await asyncio.sleep(1) # Do work... except asyncio.CancelledError: # Clean up resources here print("Task was cancelled, cleaning up...") raise # Re-raise so caller knows task was cancelle