I’m unable to exit a playwright loop cleanly on KeyboardInterrupt/Exception
. It is called by subprocess()
in our CICD and always fails due to this garble when the system sends <ctrl+c> after running for its slotted time:
(simplified example with google)
#!/usr/bin/env python3
"""
pip install playwright
playwright install
playwright install-deps
"""
import argparse, json, platform, sys, time
from playwright.sync_api import sync_playwright
url = "https://www.google.no"
parser = argparse.ArgumentParser(description='playwright example')
parser.add_argument('--browser', help='browser type', choices=['chrome','firefox','msedge','webkit'], default='chrome')
parser.add_argument('--headed', help='set to set headed with browser', action='store_true')
args, unknown_args = parser.parse_known_args()
if unknown_args:
print(f"unknown parameters: {unknown_args}")
sys.exit(-1)
args.headless = True
if args.headed:
args.headless = False
if platform.system()!='Darwin' and args.browser=='webkit':
print("webkit only supported on apple")
sys.exit(-1)
p = sync_playwright().start()
t0 = time.time()
if args.browser=='firefox':
browser = p.firefox.launch(headless=args.headless)
elif args.browser=='chrome':
browser = p.chromium.launch(channel='chrome', headless=args.headless)
elif args.browser=='msedge':
browser = p.chromium.launch(channel='msedge', headless=args.headless)
elif args.browser=='webkit':
browser = p.webkit.launch(headless=args.headless)
page = browser.new_page()
searches = ["python", "playwright", "selenium", "requests", "beautifulsoup"]
for search in searches:
try:
t1 = time.time()
page.goto(url)
try:
page.get_by_role("button", name="Godta alle").click(timeout=1000)
except Exception as e:
pass
page.get_by_label("Søk", exact=True).type(search)
page.get_by_label("Søk", exact=True).press("Enter")
page.locator("#tsf").get_by_role("button", name="Søk", exact=True)
time.sleep(1)
page.screenshot(path=f"pics/google-{search}.png")
except Exception:
browser.close()
sys.exit(0)
When I exit with <ctrl+c> It fails on closing the browser
Traceback (most recent call last):
File "C:disttestingexit-test.py", line 59, in <module>
browser.close()
File "C:distvenvstestingLibsite-packagesplaywrightsync_api_generated.py", line 13927, in close
return mapping.from_maybe_impl(self._sync(self._impl_obj.close(reason=reason)))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:distvenvstestingLibsite-packagesplaywright_impl_sync_base.py", line 115, in _sync
return task.result()
^^^^^^^^^^^^^
File "C:distvenvstestingLibsite-packagesplaywright_impl_browser.py", line 192, in close
raise e
File "C:distvenvstestingLibsite-packagesplaywright_impl_browser.py", line 189, in close
await self._channel.send("close", {"reason": reason})
File "C:distvenvstestingLibsite-packagesplaywright_impl_connection.py", line 59, in send
return await self._connection.wrap_api_call(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:distvenvstestingLibsite-packagesplaywright_impl_connection.py", line 514, in wrap_api_call
raise rewrite_error(error, f"{parsed_st['apiName']}: {error}") from None
Exception: Browser.close: Connection closed while reading from the driver
if I just do:
:
except KeyboardInterrupt:
sys.exit(0)
I manage to get it clean sometimes, but mostly:
Exception ignored in: <function BaseSubprocessTransport.__del__ at 0x00000242299C2A20>
Traceback (most recent call last):
File "C:distpython312Libasynciobase_subprocess.py", line 126, in __del__
File "C:distpython312Libasynciobase_subprocess.py", line 104, in close
File "C:distpython312Libasyncioproactor_events.py", line 109, in close
File "C:distpython312Libasynciobase_events.py", line 795, in call_soon
File "C:distpython312Libasynciobase_events.py", line 541, in _check_closed
RuntimeError: Event loop is closed
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x00000242299E8220>
Traceback (most recent call last):
File "C:distpython312Libasyncioproactor_events.py", line 116, in __del__
File "C:distpython312Libasyncioproactor_events.py", line 80, in __repr__
File "C:distpython312Libasynciowindows_utils.py", line 102, in fileno
ValueError: I/O operation on closed pipe
Task was destroyed but it is pending!
task: <Task pending name='Task-12' coro=<Locator.click() running at C:distvenvstestingLibsite-packagesplaywright_impl_locator.py:156> wait_for=<Future pending cb=[Task.task_wakeup()]> cb=[SyncBase._sync.<locals>.<lambda>() at C:distvenvstestingLibsite-packagesplaywright_impl_sync_base.py:111, ProtocolCallback.__init__.<locals>.cb() at C:distvenvstestingLibsite-packagesplaywright_impl_connection.py:191]>
Any hints greatly appreciated 🙂
4