pronron
pronron

Reputation: 33

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?

Upvotes: 3

Views: 583

Answers (1)

ggorlen
ggorlen

Reputation: 57195

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.

Upvotes: 0

Related Questions