You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We have a handful of methods which we are unable to convert to async due to the third-party dependencies which are synchronous. In these methods, we tend to retrieve a json body using something like body = asyncio.run(request.json()).
This works the way you would expect when running the actual server and pointing a real client at it; however, when we try to test using TestClient, this results in the following exception when we hit the asyncio.run line in the server code:
RuntimeError: <asyncio.locks.Event object at 0x<some id> [unset, waiters:1]> is bound to a different event loop
The bottom of the stack looks like this:
my_api/api/routers/my_router.py:50: in post
data = asyncio.run(request.json())
python3.10/asyncio/runners.py:44: in run
return loop.run_until_complete(main)
python3.10/asyncio/base_events.py:649: in run_until_complete
return future.result()
starlette/requests.py:243: in json
body = await self.body()
starlette/requests.py:236: in body
async for chunk in self.stream():
starlette/requests.py:221: in stream
message = await self._receive()
starlette/middleware/base.py:39: in receive_or_disconnect
async with anyio.create_task_group() as task_group:
and then inside the task group we blow up:
starlette/middleware/base.py, line 42, in wrap
result = await func()
anyio/_backends/_asyncio.py, line 1842, in wait
if await self._event.wait():
asyncio/locks.py, line 211, in wait
fut = self._get_loop().create_future()
asyncio/mixins.py, line 30, in _get_loop
raise RuntimeError(f'{self!r} is bound to a different event loop')
I don't know a great deal about the internals of Starlette's request & response classes, but presumably the issue is that whatever TestClient is doing mixed with what our server code is doing causes a different event loop to be trying to consume the response than the event loop that the TestClient is using to try to generate the response, and then badness ensues.
If the answer is "don't use TestClient" then I'm happy to drop it for something else like async-asgi-testclient, but it might be nice to find a way to make this work properly if one exists.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
We have a handful of methods which we are unable to convert to async due to the third-party dependencies which are synchronous. In these methods, we tend to retrieve a json body using something like
body = asyncio.run(request.json())
.This works the way you would expect when running the actual server and pointing a real client at it; however, when we try to test using TestClient, this results in the following exception when we hit the
asyncio.run
line in the server code:RuntimeError: <asyncio.locks.Event object at 0x<some id> [unset, waiters:1]> is bound to a different event loop
The bottom of the stack looks like this:
and then inside the task group we blow up:
I don't know a great deal about the internals of Starlette's request & response classes, but presumably the issue is that whatever TestClient is doing mixed with what our server code is doing causes a different event loop to be trying to consume the response than the event loop that the TestClient is using to try to generate the response, and then badness ensues.
If the answer is "don't use TestClient" then I'm happy to drop it for something else like async-asgi-testclient, but it might be nice to find a way to make this work properly if one exists.
Beta Was this translation helpful? Give feedback.
All reactions