channels: Django 3 + channels - runserver does not work with autoreload
I am trying to set up an example repo for Django 3 + ariadne + channels.
I have added channels and ariadne to the top of INSTALLED_APPS
ASGI_APPLICATION = "server.routing.application"
INSTALLED_APPS = [
"channels",
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"ariadne.contrib.django",
]
And set up routing.py
:
from typing import Callable
from ariadne.asgi import GraphQL
from channels.routing import URLRouter, ProtocolTypeRouter
from django.core.handlers.asgi import ASGIHandler
from django.urls import path, re_path
from gql.schema import schema
# This is an ASGI2 compatibility class so that we can use ariadne
# subscriptions with channels.
# Once channels supports ASGI3 this class can go away:
# https://github.com/mirumee/ariadne/issues/210
class DjangoChannelsGraphQL(GraphQL):
def __call__(self, scope) -> Callable:
async def handle(receive, send):
await super(DjangoChannelsGraphQL, self).__call__(scope, receive, send)
return handle
application = ProtocolTypeRouter(
{
"websocket": URLRouter(
[path("graphql/", DjangoChannelsGraphQL(schema, debug=True))]
),
"http": URLRouter(
[
path("graphql/", DjangoChannelsGraphQL(schema, debug=True)),
re_path(r"", ASGIHandler),
]
),
}
)
When I run python manage.py runserver
I get hit with django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.
I don’t quite understand channels’ runserver config, but I’ll include trace for a good measuer:
November 02, 2019 - 16:48:08
Django version 3.0b1, using settings 'server.settings'
Starting ASGI/Channels version 2.3.1 development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
/Users/swistak/messenger/.venv/lib/python3.7/site-packages/channels/management/commands/runserver.py changed, reloading.
Traceback (most recent call last):
File "/Users/swistak/messenger/.venv/lib/python3.7/site-packages/django/core/management/base.py", line 328, in run_from_argv
self.execute(*args, **cmd_options)
File "/Users/swistak/messenger/.venv/lib/python3.7/site-packages/django/core/management/commands/runserver.py", line 60, in execute
super().execute(*args, **options)
File "/Users/swistak/messenger/.venv/lib/python3.7/site-packages/django/core/management/base.py", line 369, in execute
output = self.handle(*args, **options)
File "/Users/swistak/messenger/.venv/lib/python3.7/site-packages/channels/management/commands/runserver.py", line 59, in handle
super().handle(*args, **options)
File "/Users/swistak/messenger/.venv/lib/python3.7/site-packages/django/core/management/commands/runserver.py", line 95, in handle
self.run(**options)
File "/Users/swistak/messenger/.venv/lib/python3.7/site-packages/django/core/management/commands/runserver.py", line 102, in run
autoreload.run_with_reloader(self.inner_run, **options)
File "/Users/swistak/messenger/.venv/lib/python3.7/site-packages/django/utils/autoreload.py", line 599, in run_with_reloader
start_django(reloader, main_func, *args, **kwargs)
File "/Users/swistak/messenger/.venv/lib/python3.7/site-packages/django/utils/autoreload.py", line 584, in start_django
reloader.run(django_main_thread)
File "/Users/swistak/messenger/.venv/lib/python3.7/site-packages/django/utils/autoreload.py", line 299, in run
self.run_loop()
File "/Users/swistak/messenger/.venv/lib/python3.7/site-packages/django/utils/autoreload.py", line 305, in run_loop
next(ticker)
File "/Users/swistak/messenger/.venv/lib/python3.7/site-packages/django/utils/autoreload.py", line 353, in tick
self.notify_file_changed(filepath)
File "/Users/swistak/messenger/.venv/lib/python3.7/site-packages/django/utils/autoreload.py", line 328, in notify_file_changed
trigger_reload(path)
File "/Users/swistak/messenger/.venv/lib/python3.7/site-packages/django/utils/autoreload.py", line 223, in trigger_reload
sys.exit(3)
SystemExit: 3
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "manage.py", line 21, in <module>
main()
File "manage.py", line 17, in main
execute_from_command_line(sys.argv)
File "/Users/swistak/messenger/.venv/lib/python3.7/site-packages/django/core/management/__init__.py", line 401, in execute_from_command_line
utility.execute()
File "/Users/swistak/messenger/.venv/lib/python3.7/site-packages/django/core/management/__init__.py", line 395, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Users/swistak/messenger/.venv/lib/python3.7/site-packages/django/core/management/base.py", line 341, in run_from_argv
connections.close_all()
File "/Users/swistak/messenger/.venv/lib/python3.7/site-packages/django/db/utils.py", line 230, in close_all
connection.close()
File "/Users/swistak/messenger/.venv/lib/python3.7/site-packages/django/utils/asyncio.py", line 22, in inner
raise SynchronousOnlyOperation(message)
django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.```
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 15 (13 by maintainers)
Commits related to this issue
- Avoid Twisted using the default event loop When switching threads, e.g. when run via Django auto-reloader, the default run loop causes issues detecting async contexts. Fixes https://github.com/django... — committed to carltongibson/daphne by carltongibson 5 years ago
- Avoid Twisted using the default event loop When switching threads, e.g. when run via Django auto-reloader, the default run loop causes issues detecting async contexts. Fixes https://github.com/django... — committed to django/daphne by carltongibson 5 years ago
- Avoid Twisted using the default event loop When switching threads, e.g. when run via Django auto-reloader, the default run loop causes issues detecting async contexts. Fixes https://github.com/django... — committed to goldentroll/daphne by goldentroll 5 years ago
Updating Daphne to 2.4.1 should see you good to go.
Thanks all.
Same for me. Autoreload triggers the following exception:
My asgi.py:
Dependencies: