Tengo problemas con la API de función de exposición de Playwright . También quiero poder pasar la página a las funciones expuestas para poder navegar, usar localizadores, etc. dentro del contexto de la función expuesta.
El problema es que la instancia de la página en la función expuesta se "desconecta" de alguna manera de su original y no realiza navegaciones, localizadores, etc. Cualquier llamada a los métodos de la página parece bloquearse indefinidamente.
Considere este ejemplo simplificado:
from playwright.sync_api import sync_playwright, Page from functools import partial def search_title(page: Page, title: str): print(title) page.goto(f"https://bing.com?q={title}") def main(): with sync_playwright() as p: browser = p.chromium.launch(headless=False) context = browser.new_context(viewport={ 'width': 1920, 'height': 1024 }) page = context.new_page() page.goto(f"https://wikipedia.org") context.expose_function("search_title", partial(handle_title, page)) page.evaluate("window.onload = () => search_title(document.title)") while True: page.wait_for_timeout(1000) if __name__ == "__main__": main()Lo que hace es imprimir el título y se detiene en el paso de navegación indefinidamente.
EDITAR : el uso de la versión asyncio del mismo código anterior produce playwright._impl._api_types.Error: Execution context was destroyed, most likely because of a navigation. error:
from playwright.async_api import Page, async_playwright import asyncio from functools import partial import time async def handle_title(page: Page, title: str): print(title) print(page) await page.goto(f"https://bing.com?q={title}") async def main(): async with async_playwright() as p: browser = await p.chromium.launch(headless=False) context = await browser.new_context(viewport={ 'width': 1920, 'height': 1024 }) page = await context.new_page() await page.goto(f"https://wikipedia.org") await context.expose_function("handle_title", partial(handle_title, page)) await page.evaluate("window.onload = () => handle_title(document.title)") while True: await asyncio.sleep(1) if __name__ == "__main__": asyncio.run(main())Descubrí que es posible usar Page en el contexto de la función expuesta, siempre que:
from playwright.async_api import Page, async_playwright import asyncio from functools import partial import time async def handle_title(page: Page, title: str): # page = page_var.get() print(page) await page.locator("#searchInput").type(f"{title}") return "hello world" async def main(): async with async_playwright() as p: browser = await p.chromium.launch(headless=False) context = await browser.new_context(viewport={ 'width': 1920, 'height': 1024 }) page = await context.new_page() await page.goto(f"https://wikipedia.org") await context.expose_function("handle_title", partial(handle_title, page)) await page.evaluate("window.onload = () => handle_title(document.title)") while True: await asyncio.sleep(1) asyncio.run(main())