12

I'm trying to use Django 3.0 with Uvicorn and getting this on start:

INFO:     Started server process [96219]
INFO:     Waiting for application startup.
INFO:     ASGI 'lifespan' protocol appears unsupported.
INFO:     Application startup complete.

I could turn lifespan off with the --lifespan off flag, but is there a way to have it work with Django? A quick search for Django + lifespan seems to not return anything.

aroooo
  • 4,726
  • 8
  • 47
  • 81

3 Answers3

8

No, lifespan protocol doesn't work with Django 3.0.

See this ticket: https://code.djangoproject.com/ticket/31508

Kuba Misiorny
  • 131
  • 1
  • 5
2

Here's the initial setup I used with django 3.1 / 3.2

EDIT: some rough performance benchmarks: https://github.com/allen-munsch/benchmark-django-fastapi

old version

your_django/old_wsgi.py:

import os

from django.core.wsgi import get_wsgi_application
from dj_static import Cling

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "your_django.settings")

application = Cling(get_wsgi_application())

Previously run as:

newrelic-admin run-program gunicorn your_django.old_wsgi \
-k eventlet --log-file - --timeout 60

new version

your_django/asgi.py:

import os

from django.core.asgi import get_asgi_application
from django.contrib.staticfiles.handlers import ASGIStaticFilesHandler

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pm.settings")

application = ASGIStaticFilesHandler(
    get_asgi_application()
)

And to run

gunicorn your_django.asgi --log-level=debug -k uvicorn.workers.UvicornWorker \
--log-file - --timeout 60

# OR for local dev

uvicorn --reload your_django.asgi

related:

jmunsch
  • 22,771
  • 11
  • 93
  • 114
2

As @KubaMisiorny pointed out. Django does not support Lifespan Protocol.

If you would like to disable this protocol, you have a couple of options depending on what your setup is.

Running uvicorn

Pass --lifespan off option.

uvicorn --lifespan off

Running gunicorn with uvicorn.workers.UvicornWorker

You will need to pass config arguments by creating a subclass of the worker class

Create uvicorn_worker.py

from uvicorn.workers import UvicornWorker as BaseUvicornWorker


# Django does not support Lifespan Protocol
# https://asgi.readthedocs.io/en/latest/specs/lifespan.html
# https://github.com/django/django/pull/13636
# https://code.djangoproject.com/ticket/31508
# Using uvicorn.workers.UvicornWorker throws INFO warning:
#   "ASGI 'lifespan' protocol appears unsupported."
# To avoid that we need to disable 'lifespan' in the worker
class UvicornWorker(BaseUvicornWorker):
    CONFIG_KWARGS = {"lifespan": "off"}

In gunicorn.conf.py

# https://www.uvicorn.org/deployment/#gunicorn
# using custom one to disable Lifespan Protocol
# needs to be passed by string https://github.com/benoitc/gunicorn/issues/1539
worker_class = "uvicorn_worker.UvicornWorker"
Sardorbek Imomaliev
  • 14,861
  • 2
  • 51
  • 63