Opened 11 months ago
Closed 11 months ago
#34998 closed Cleanup/optimization (wontfix)
Raising a StopIteration in asynchronous mode hangs the request
Reported by: | Clément Escolano | Owned by: | nobody |
---|---|---|---|
Component: | Core (Other) | Version: | 4.2 |
Severity: | Normal | Keywords: | |
Cc: | Carlton Gibson, Andrew Godwin | Triage Stage: | Unreviewed |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
When using Django in Asynchronous mode, if some code raises a StopIteration
error (generally when calling next()
on an empty generator), the request hangs. I think Django should handle the error gracefully (display a 500 error page) instead.
Basically, when the code raises a StopIteration
error, the following is displayed and the request hangs:
TypeError: StopIteration interacts badly with generators and cannot be raised into a Future
I have reproduce the issue with a minimal project here: https://github.com/clement-escolano/django-stopiteration
Relevant file is stopiteration/views.py
which is a view called on /error
endpoint and contains:
def error(request): next(i for i in []) return None
The Django application must be run with asynchronous support. For instance with: uvicorn test_stopiteration.asgi:application
.
Change History (4)
comment:1 by , 11 months ago
Cc: | added |
---|
comment:2 by , 11 months ago
Cc: | added |
---|
Good issue. AFAICS this is https://github.com/python/cpython/issues/112182
See also https://github.com/agronholm/anyio/pull/477 and https://github.com/tiangolo/fastapi/issues/966 — aynio was able to work around it, but it's not clear we're going to be able to doing anything pending a fix in asyncio.
To quote Guido from the Python issue:
My first response is "don't do that". That's why it prints such an elaborate warning.
Short of a concrete suggestion, 🤷♀️
comment:3 by , 11 months ago
Hmm yes, this is one of those nasty bugs that reveals the true nature of how Python async works.
In testing this locally with just plain async functions, I don't see how we can catch this - the error happens when you return StopIteration from _any_ awaited function, you can't wrap around it to catch it instead. Given that views are always going to be async functions, unless we want to wrap every single view, decorator and middleware in our own custom Future it's not going to be reasonable to catch it.
comment:4 by , 11 months ago
Component: | Uncategorized → Core (Other) |
---|---|
Resolution: | → wontfix |
Status: | new → closed |
Type: | Uncategorized → Cleanup/optimization |
Thanks for comments!
Closing as "wontfix" unless someone can prove it's actionable in Django itself.
Is it not a duplicate of #33795, #32798, or #33735?