pyodide / pyodide/pytest-pyodide
Exception ignored in PyodideHandle.__del__ playwright._impl._errors.Error: Event loop is closed! Is Playwright already stopped?
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 38
- Forks
- 20
- Avg merge
- 1d 23h
- Merged PRs (30d)
- 1
Description
Using a PyodideHandle in a fixture with the playwright runner, I am seeing a warning about an ignored exception when cleaning up the test.
Test case:
# tomtests/test_handle_bug.py
import pytest
from pytest_pyodide import run_in_pyodide
@pytest.fixture
@run_in_pyodide
def macguffin(selenium):
from pytest_pyodide.decorator import PyodideHandle
s = {"a": 1}
return PyodideHandle(s)
@run_in_pyodide
def test_macguffin(selenium, macguffin):
assert macguffin["a"] == 1
# uv sync --all-extras
# uv run pytest --runner playwright --rt chrome tomtests/
Also pushed here: https://github.com/tomjakubowski/pytest-pyodide/commit/23cd2191101cfb40eafab23bc9b9614b37361e4a
Error message:
Exception ignored in: <function PyodideHandle.__del__ at 0x101ffa3e0>
Traceback (most recent call last):
File "/Users/tom/github.com/pyodide/pytest-pyodide/pytest_pyodide/decorator.py", line 88, in __del__
self.selenium.run_js(
File "/Users/tom/github.com/pyodide/pytest-pyodide/pytest_pyodide/runner.py", line 262, in run_js
return self.run_js_inner(code, check_code)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/pytest_pyodide/runner.py", line 415, in run_js_inner
retval = self.driver.evaluate(wrapper % (code, check_code))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/playwright/sync_api/_generated.py", line 8530, in evaluate
self._sync(
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/playwright/_impl/_sync_base.py", line 104, in _sync
raise Error("Event loop is closed! Is Playwright already stopped?")
playwright._impl._errors.Error: Event loop is closed! Is Playwright already stopped?
Note that this doesn't cause the test to fail, and the exit code is 0.
I see a similar error message when running with --runner selenium:
Exception ignored in: <function PyodideHandle.__del__ at 0x1032263e0>
Traceback (most recent call last):
File "/Users/tom/github.com/pyodide/pytest-pyodide/pytest_pyodide/decorator.py", line 88, in __del__
self.selenium.run_js(
File "/Users/tom/github.com/pyodide/pytest-pyodide/pytest_pyodide/runner.py", line 262, in run_js
return self.run_js_inner(code, check_code)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/pytest_pyodide/runner.py", line 362, in run_js_inner
retval = self.driver.execute_async_script(wrapper % (code, check_code))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/selenium/webdriver/remote/webdriver.py", line 550, in execute_async_script
return self.execute(command, {"script": script, "args": converted_args})["value"]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/selenium/webdriver/remote/webdriver.py", line 427, in execute
response = self.command_executor.execute(driver_command, params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/selenium/webdriver/remote/remote_connection.py", line 404, in execute
return self._request(command_info[0], url, body=data)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/selenium/webdriver/remote/remote_connection.py", line 428, in _request
response = self._conn.request(method, url, body=body, headers=headers, timeout=self._client_config.timeout)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/urllib3/_request_methods.py", line 143, in request
return self.request_encode_body(
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/urllib3/_request_methods.py", line 278, in request_encode_body
return self.urlopen(method, url, **extra_kw)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/urllib3/poolmanager.py", line 443, in urlopen
response = conn.urlopen(method, u.request_uri, **kw)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/urllib3/connectionpool.py", line 871, in urlopen
return self.urlopen(
^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/urllib3/connectionpool.py", line 871, in urlopen
return self.urlopen(
^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/urllib3/connectionpool.py", line 871, in urlopen
return self.urlopen(
^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/urllib3/connectionpool.py", line 841, in urlopen
retries = retries.increment(
^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/urllib3/util/retry.py", line 519, in increment
raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=60847): Max retries exceeded with url: /session/d6624be6a6c2269e04186b871e101b60/execute/async (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x1034bb7a0>: Failed to establish a new connection: [Errno 61] Connection refused'))
I think that the handle's finalizer is being called after the event loop is closed, and the call to eval the reference count decrement is what's throwing.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with PyodideHandle.del in pytest_pyodide/decorator.py and the run_js paths in pytest_pyodide/runner.py. Reproduce the fixture with the provided pytest commands using the Playwright and Selenium runners. Done means cleanup no longer emits an ignored exception after the browser or event loop has closed, while the test still exits successfully.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- playwright, python
- Domain
- testing-qa
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100