Uvicorn: Exception thrown when running Django with ASGI/Uvicorn/Gunicorn

Created on 1 Jul 2020  路  5Comments  路  Source: encode/uvicorn

Hi,

I'm honestly not sure if this is a uvicorn issue, a Gunicorn issue or a Django issue - but I'll start here, since I don't see the same exceptions if I just replace uvicorn with Daphne.

We're running some experiments using ASGI instead of WSGI for our Django projects, and our go-to has been uvicorn, since we already use this in some starlette projects - we love using it.

And it works - for the most parts. But when Gunicorn starts for the first time, we get an exception (per worker): Django can only handle ASGI/HTTP connections, not lifespan.

I don't have the specific trace, but it happens in the Django ASGI handler.

Now, I realise that this happens inside Django code - but what makes me post here first, is that it doesn't happen if we use Daphne. I'm assuming (without knowing anything about the internals, so I might be very wrong), that when uvicorn is spun up within Gunicorn, it attempts to set up a lifespan protocol, and this causes the issue with Django. However, as far as I can see, it's not possible to set the lifespan implementation to off, when the uvicorn worker class is used.

If I'm completely off base here, please let me know, and I'll try to direct this to a different place.

Most helpful comment

For the time begin we've made this custom worker class to get rid of the issue as per your suggestion, and it does indeed work:

from uvicorn.workers import UvicornWorker as BaseUvicornWorker


class UvicornWorker(BaseUvicornWorker):
    CONFIG_KWARGS = {"loop": "uvloop", "http": "httptools", "lifespan": "off"}

All 5 comments

Probably worth using --lifespan off, tho it'd be more graceful not to have to do so here.

@tomchristie Can we actually supply this to Gunicorn? I thought it was only possible to supply this, if you use uvicorn directly?

Right, yes.

For the time begin we've made this custom worker class to get rid of the issue as per your suggestion, and it does indeed work:

from uvicorn.workers import UvicornWorker as BaseUvicornWorker


class UvicornWorker(BaseUvicornWorker):
    CONFIG_KWARGS = {"loop": "uvloop", "http": "httptools", "lifespan": "off"}

I will close this @HenrikOssipoff in favor of https://github.com/encode/uvicorn/issues/266 as it's the same gunicorn worker config problematic that is easily solved by subclassing the UvicornWorker which you did perfectly !

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rspadim picture rspadim  路  5Comments

itayperl picture itayperl  路  3Comments

toonknapen picture toonknapen  路  5Comments

Gyllsdorff picture Gyllsdorff  路  6Comments

adriangallegos picture adriangallegos  路  6Comments