Skip to content
This repository has been archived by the owner on Oct 1, 2024. It is now read-only.

Python 3.10: RuntimeError: Event loop is closed/Task attached to a different loop #382

Open
RamonGiovane opened this issue Jun 16, 2024 · 1 comment

Comments

@RamonGiovane
Copy link

RamonGiovane commented Jun 16, 2024

Description

I'm unable to update Ward to version 0.67.0b0 or later.
When I run Ward async tests for FastAPI + SQLAlchemy async, this shows on console in the middle of the test execution:

Exception closing connection <AdaptedConnection <asyncpg.connection.Connection object at 0x7fa78460a420>>
Traceback (most recent call last):
  File "/home/ramon/project/.venv/lib/python3.10/site-packages/sqlalchemy/pool/base.py", line 928, in _checkout
    result = pool._dialect.do_ping(fairy.dbapi_connection)
  File "/home/ramon/project/.venv/lib/python3.10/site-packages/sqlalchemy/engine/default.py", line 703, in do_ping
    cursor.execute(self._dialect_specific_select_one)
  File "/home/ramon/project/.venv/lib/python3.10/site-packages/sqlalchemy/dialects/postgresql/asyncpg.py", line 479, in execute
    self._adapt_connection.await_(
  File "/home/ramon/project/.venv/lib/python3.10/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 68, in await_only
    return current.driver.switch(awaitable)
  File "/home/ramon/project/.venv/lib/python3.10/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 121, in greenlet_spawn
    value = await result
  File "/home/ramon/project/.venv/lib/python3.10/site-packages/sqlalchemy/dialects/postgresql/asyncpg.py", line 408, in _prepare_and_execute
    await adapt_connection._start_transaction()
  File "/home/ramon/project/.venv/lib/python3.10/site-packages/sqlalchemy/dialects/postgresql/asyncpg.py", line 716, in _start_transaction
    self._handle_exception(error)
  File "/home/ramon/project/.venv/lib/python3.10/site-packages/sqlalchemy/dialects/postgresql/asyncpg.py", line 684, in _handle_exception
    raise error
  File "/home/ramon/project/.venv/lib/python3.10/site-packages/sqlalchemy/dialects/postgresql/asyncpg.py", line 714, in _start_transaction
    await self._transaction.start()
  File "/home/ramon/project/.venv/lib/python3.10/site-packages/asyncpg/transaction.py", line 138, in start
    await self._connection.execute(query)
  File "/home/ramon/project/.venv/lib/python3.10/site-packages/asyncpg/connection.py", line 318, in execute
    return await self._protocol.query(query, timeout)
  File "asyncpg/protocol/protocol.pyx", line 338, in query
RuntimeError: Task <Task pending name='Task-9' coro=<_() running at /home/ramon/project/tests/api/test_application_route.py:98> cb=[_run_until_complete_cb() at 
/home/ramon/.asdf/installs/python/3.10.11/lib/python3.10/asyncio/base_events.py:184]> got Future <Future pending cb=[Protocol._on_waiter_completed()]> attached to a different loop

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/ramon/project/.venv/lib/python3.10/site-packages/sqlalchemy/pool/base.py", line 260, in _close_connection
    self._dialect.do_terminate(connection)
  File "/home/ramon/project/.venv/lib/python3.10/site-packages/sqlalchemy/dialects/postgresql/asyncpg.py", line 995, in do_terminate
    dbapi_connection.terminate()
  File "/home/ramon/project/.venv/lib/python3.10/site-packages/sqlalchemy/dialects/postgresql/asyncpg.py", line 752, in terminate
    self._connection.terminate()
  File "/home/ramon/project/.venv/lib/python3.10/site-packages/asyncpg/connection.py", line 1345, in terminate
    self._abort()
  File "/home/ramon/project/.venv/lib/python3.10/site-packages/asyncpg/connection.py", line 1372, in _abort
    self._protocol.abort()
  File "asyncpg/protocol/protocol.pyx", line 569, in asyncpg.protocol.protocol.BaseProtocol.abort
  File "asyncpg/protocol/protocol.pyx", line 668, in asyncpg.protocol.protocol.BaseProtocol._handle_waiter_on_connection_lost
  File "/home/ramon/.asdf/installs/python/3.10.11/lib/python3.10/asyncio/base_events.py", line 753, in call_soon
    self._check_closed()
  File "/home/ramon/.asdf/installs/python/3.10.11/lib/python3.10/asyncio/base_events.py", line 515, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

Then on Ward's test results, we got this message:

RuntimeError: Task <Task pending name='starlette.middleware.base.BaseHTTPMiddleware.__call__.<locals>.call_next.<locals>.coro'
coro=<BaseHTTPMiddleware.__call__.<locals>.call_next.<locals>.coro()
running at /home/ramon/project/.venv/lib/python3.10/site-packages/starlette/middleware/base.py:34> cb=[TaskGroup._spawn.<locals>.task_done() at 
/home/ramon/project/.venv/lib/python3.10/site-packages/anyio/_backends/_asyncio.py:661]>
got Future <Future pending cb=[Protocol._on_waiter_completed()]> attached to a 
different loop

I guess this was introduced in PR #334

My specs

Python 3.10.11
Ward 0.67.0b0

Expected behavior

The test to work like it did on previous Ward version 0.66.1b0

Possible solution:

Instead of using asyncio.run() I think we should still try get the current event loop. This approach may work https://stackoverflow.com/a/73884759

@RamonGiovane RamonGiovane changed the title Python 3.10: RuntimeError: Task attached to a different loop Python 3.10: RuntimeError: Event loop is closed/Task attached to a different loop Jun 16, 2024
@petereon
Copy link
Contributor

petereon commented Aug 18, 2024

@RamonGiovane can you try to build ward including the changes in my PR to verify?
Also, do you have minimal reproduction, so we could include a proper test?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants