pythonpython-3.xplaywrightplaywright-python

ERROR:"It looks like you are using Playwright Sync API inside the asyncio loop. Please use the Async API instead."


I have this setup

File 1

from playwright.sync_api import sync_playwright


class A:
   def __init__(self,login_dict):
       self.start = sync_playwright().start()
       self.browser = self.start.chromium.launch()
       self.context = self.browser.new_context()
       self.page = self.context.new_page()
       self.login_dict = login_dict

File 2

import file_1.py

class B(A):
    def __init__(self):
       super().__init__()

from file_1 import A
from file_2 import B

a = A(some_login_dict)
b = B()

I get this error at the super init of B class

It looks like you are using Playwright Sync API inside the asyncio loop. Please use the Async API instead.

I do not understand why is this happening, can someone explain? Is there a way to avoid this?


Solution

  • The files and classes in your code are obscuring the root cause. Nonetheless, it's good to see your intended use case, since you'd normally start Playwright with a with context manager, which isn't as obvious in the class setup.

    The minimal trigger is simply starting Playwright's sync API twice, which it wasn't designed to do:

    from playwright.sync_api import sync_playwright  # 1.48.0
    
    
    browser = sync_playwright().start().chromium.launch()
    browser = sync_playwright().start().chromium.launch()  # raises 'It looks like...'
    

    The error message is not very clear.

    The solution is to only .start() Playwright once for the application:

    from playwright.sync_api import sync_playwright
    
    
    sync_playwright = sync_playwright().start()
    
    browser = sync_playwright.chromium.launch()
    browser = sync_playwright.chromium.launch()
    

    In your code, the error occurs when you initialize both A() and B() (removing one initializer or the other works).

    Since you're working with classes, you can move playwright = sync_playwright().start() to the module-level scope of a shared, one-off module, which is then imported from any other file that needs to launch a browser.

    An alternative approach is to use the async API, which doesn't seem to mind being started multiple times:

    import asyncio
    from playwright.async_api import async_playwright
    
    
    async def run():
        pw1 = await async_playwright().start()
        pw2 = await async_playwright().start()
        browser1 = await pw1.chromium.launch()
        browser2 = await pw2.chromium.launch()
        page1 = await browser1.new_page()
        page2 = await browser2.new_page()
        await page1.goto("https://www.example.com")
        await page2.goto("https://en.wikipedia.org")
        print(await page1.title())
        print(await page2.title())
        await pw1.stop()
        await pw2.stop()
    
    
    asyncio.run(run())
    

    Remember to clean up with .stop() when not using context-managed Playwright.

    See also Playwright issue #1391 on GitHub.