The last statement in your Python code hangs because you are mixing synchronous and asynchronous code incorrectly. Here’s why:
The Problem
asyncio.run is designed to run a single coroutine and manage the event loop. It creates a new event loop, runs the coroutine, and then closes the loop.
- In your code, you call
asyncio.run twice:
asyncio.run(async_playwright().start()) starts Playwright and returns a Playwright object (p).
asyncio.run(p.firefox.launch(headless=False)) tries to launch a browser, but this is problematic because:
- The first
asyncio.run already closed the event loop after starting Playwright.
- The second
asyncio.run tries to create a new event loop, but Playwright was started in the previous loop, which is now closed. This leads to a conflict and the code hangs.
How to Fix It
You should use a single asyncio.run and structure your code as a single coroutine:
import asyncio
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
browser = await p.firefox.launch(headless=False)
# Do something with the browser here
await browser.close()
asyncio.run(main())
Key Points:
- Use
async with to manage the Playwright context.
- Use a single
asyncio.run to run the entire async workflow.
- Always
await async functions like launch.
This way, the event loop is managed correctly, and the code will not hang.