playwright-python
playwright-python copied to clipboard
[BUG] Terminating the Selenium Grid script freezes Playwright
Context:
- Playwright Version: 1.18.2
- Operating System: Linux 5.10 Ubuntu 20.04.3 on WSL2
- Python version: 3.10.1
- Node.js version: 14.17.2
- Browser: Chromium in the Selenium Grid container
Code Snippet
import time
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
try:
page = browser.new_page()
page.goto('https://en.wikipedia.org')
print('sleeping...')
time.sleep(10)
finally:
browser.close()
Describe the bug
I'm running a Selenium Grid container:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6b005a57908f selenium/standalone-chrome:4.1.2-20220208 "/opt/bin/entry_poin…" 20 minutes ago Up 15 minutes 0.0.0.0:4444->4444/tcp, :::4444->4444/tcp, 0.0.0.0:5900->5900/tcp, :::5900->5900/tcp playground_selenium_1
Sending a SIGINT to the script while it sleeps freezes the process. Sending it again crashes the process with the following:
$ env SELENIUM_REMOTE_URL=http://localhost:4444/wd/hub python playwright_playground.py
sleeping...
^C
^CTraceback (most recent call last):
File "/home/sviatoslav/Workspace/playground/playwright_playground.py", line 11, in <module>
time.sleep(10)
KeyboardInterrupt
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/sviatoslav/Workspace/playground/playwright_playground.py", line 13, in <module>
browser.close()
File "/home/sviatoslav/Workspace/playground/env/lib/python3.10/site-packages/playwright/sync_api/_generated.py", line 11153, in close
self._sync("browser.close", self._impl_obj.close())
File "/home/sviatoslav/Workspace/playground/env/lib/python3.10/site-packages/playwright/_impl/_sync_base.py", line 109, in _sync
self._dispatcher_fiber.switch()
KeyboardInterrupt
Task was destroyed but it is pending!
task: <Task pending name='Task-7' coro=<Browser.close() done, defined at /home/sviatoslav/Workspace/playground/env/lib/python3.10/site-packages/playwright/_impl/_browser.py:164> wait_for=<Future pending cb=[Task.task_wakeup()]> cb=[SyncBase._sync.<locals>.callback() at /home/sviatoslav/Workspace/playground/env/lib/python3.10/site-packages/playwright/_impl/_sync_base.py:104]>
After this the Selenium session is left open. New connections to it fail, the Selenium container usually has to be restarted.
I've experienced this both with the headed and the headless modes. This doesn't happen when I don't use Selenium, i.e. closing the browser that runs natively works fine.
https://playwright.dev/python/docs/intro#timesleep-leads-to-outdated-state - you can't use time.sleep!
Sorry, my bad! However, the same happens if I change sleep to wait_for_timeout.
$ env SELENIUM_REMOTE_URL=http://localhost:4444/wd/hub python playwright_playground.py
sleeping...
^C
^CTraceback (most recent call last):
File "/home/sviatoslav/Workspace/playground/playwright_playground.py", line 9, in <module>
page.wait_for_timeout(5000)
File "/home/sviatoslav/Workspace/playground/env/lib/python3.10/site-packages/playwright/sync_api/_generated.py", line 9035, in wait_for_timeout
self._sync(
File "/home/sviatoslav/Workspace/playground/env/lib/python3.10/site-packages/playwright/_impl/_sync_base.py", line 109, in _sync
self._dispatcher_fiber.switch()
File "/home/sviatoslav/Workspace/playground/env/lib/python3.10/site-packages/playwright/sync_api/_context_manager.py", line 48, in greenlet_main
loop.run_until_complete(self._connection.run_as_sync())
File "/home/sviatoslav/.pyenv/versions/3.10.1/lib/python3.10/asyncio/base_events.py", line 628, in run_until_complete
self.run_forever()
File "/home/sviatoslav/.pyenv/versions/3.10.1/lib/python3.10/asyncio/base_events.py", line 595, in run_forever
self._run_once()
File "/home/sviatoslav/.pyenv/versions/3.10.1/lib/python3.10/asyncio/base_events.py", line 1845, in _run_once
event_list = self._selector.select(timeout)
File "/home/sviatoslav/.pyenv/versions/3.10.1/lib/python3.10/selectors.py", line 469, in select
fd_event_list = self._selector.poll(timeout, max_ev)
KeyboardInterrupt
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/sviatoslav/Workspace/playground/playwright_playground.py", line 11, in <module>
browser.close()
File "/home/sviatoslav/Workspace/playground/env/lib/python3.10/site-packages/playwright/sync_api/_generated.py", line 11153, in close
self._sync("browser.close", self._impl_obj.close())
File "/home/sviatoslav/Workspace/playground/env/lib/python3.10/site-packages/playwright/_impl/_sync_base.py", line 109, in _sync
self._dispatcher_fiber.switch()
KeyboardInterrupt
Task was destroyed but it is pending!
task: <Task pending name='Task-8' coro=<Browser.close() running at /home/sviatoslav/Workspace/playground/env/lib/python3.10/site-packages/playwright/_impl/_browser.py:164> cb=[SyncBase._sync.<locals>.callback() at /home/sviatoslav/Workspace/playground/env/lib/python3.10/site-packages/playwright/_impl/_sync_base.py:104]>
/home/sviatoslav/.pyenv/versions/3.10.1/lib/python3.10/asyncio/base_events.py:666: RuntimeWarning: coroutine 'Browser.close' was never awaited
Exception ignored in: <function BaseSubprocessTransport.__del__ at 0x7f16f9e47760>
Traceback (most recent call last):
File "/home/sviatoslav/.pyenv/versions/3.10.1/lib/python3.10/asyncio/base_subprocess.py", line 126, in __del__
File "/home/sviatoslav/.pyenv/versions/3.10.1/lib/python3.10/asyncio/base_subprocess.py", line 104, in close
File "/home/sviatoslav/.pyenv/versions/3.10.1/lib/python3.10/asyncio/unix_events.py", line 546, in close
File "/home/sviatoslav/.pyenv/versions/3.10.1/lib/python3.10/asyncio/unix_events.py", line 570, in _close
File "/home/sviatoslav/.pyenv/versions/3.10.1/lib/python3.10/asyncio/base_events.py", line 745, in call_soon
File "/home/sviatoslav/.pyenv/versions/3.10.1/lib/python3.10/asyncio/base_events.py", line 510, in _check_closed
RuntimeError: Event loop is closed
Task was destroyed but it is pending!
task: <Task pending name='Task-7' coro=<Page.wait_for_timeout() done, defined at /home/sviatoslav/Workspace/playground/env/lib/python3.10/site-packages/playwright/_impl/_page.py:823> wait_for=<Future pending cb=[Task.task_wakeup()]> cb=[SyncBase._sync.<locals>.callback() at /home/sviatoslav/Workspace/playground/env/lib/python3.10/site-packages/playwright/_impl/_sync_base.py:104]>
I was able to reproduce it, its not related to Selenium, its related to the sync exception handling.
Maybe related to https://github.com/microsoft/playwright-python/issues/818?
I have the same problem
log-info- [web run] OnAfter run event!
F:\devTools\Python-3.7\lib\site-packages\behave\runner.py:585: RuntimeWarning: coroutine 'Browser.close' was never awaited
statement.error_message = error_message
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Sorry for the late reply. Was able to reproduce it without Selenium as well in the sync and async version.
The intended behaviour would be that wait_for_timeout will throw the KeyboardInterrupt exception.
docker run -p 4444:4444 -p 7900:7900 --shm-size="2g" --rm -e SE_OPTS="--host localhost" selenium/standalone-chrome:4.3.0-20220726
Relates https://github.com/microsoft/playwright-python/pull/819/files