Traté de hacer una aplicación de chat con django-channels . Pero ocurre un RuntimeError cuando creo un nuevo proyecto django-chanels y edito datos en el sitio de administración.
No estoy seguro de pensar que el error ocurrió porque hice varios proyectos django-channels .
Cuando construí mi primer proyecto, WebSocket no funciona, así que hice otro segundo, tercero y cuarto proyecto con django-channels . Ahora WebSocket está conectado, pero tengo problemas con RuntimeError (mensaje de error: el ejecutor de un solo subproceso ya es usuario, se interbloquearía)
¿Qué puedo hacer para arreglar esto?
miproyecto/configuraciones.py
import os from pathlib import Path # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = "django-insecure-is!$&voe3y058!2sus9egmxh@d!$)=l&o8_vl=m8zz!ap+d#a#" # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", "users.apps.UsersConfig", "channels", "core.apps.CoreConfig", "broadcasts.apps.BroadcastsConfig", ] MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", ] ROOT_URLCONF = "busker.urls" TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [], "APP_DIRS": True, "OPTIONS": { "context_processors": [ "django.template.context_processors.debug", "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", ], }, }, ] WSGI_APPLICATION = "busker.wsgi.application" # Database # https://docs.djangoproject.com/en/3.2/ref/settings/#databases DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", "NAME": BASE_DIR / "db.sqlite3", } } # Password validation # https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", }, { "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", }, { "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", }, { "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", }, ] # Internationalization # https://docs.djangoproject.com/en/3.2/topics/i18n/ LANGUAGE_CODE = "en-us" TIME_ZONE = "UTC" USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.2/howto/static-files/ STATIC_URL = "/static/" STATICFILES_DIRS = [os.path.join(BASE_DIR, "static")] # Default primary key field type # https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" ASGI_APPLICATION = "busker.asgi.application" CHANNEL_LAYERS = {"default": {"BACKEND": "channels.layers.InMemoryChannelLayer"}} AUTH_USER_MODEL = "users.User"miproyecto/asgi.py
import os from channels.routing import ProtocolTypeRouter, URLRouter from django.core.asgi import get_asgi_application from channels.auth import AuthMiddlewareStack import broadcasts.routing os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") application = ProtocolTypeRouter( { "http": get_asgi_application(), # Just HTTP for now. (We can add other protocols later.) "websocket": AuthMiddlewareStack( URLRouter(broadcasts.routing.websocket_urlpatterns) ), } )miaplicación/consumidores.py
import json from channels.generic.websocket import AsyncWebsocketConsumer class ChatConsumer(AsyncWebsocketConsumer): async def connect(self): self.room_group_name = "Test-Room" await self.channel_layer.group_add(self.room_group_name, self.channel_name) await self.accept() async def disconnect(self, close_code): await self.channel_layer.group_discard(self.room_group_name, self.channel_name) print("Disconnected!") async def receive(self, text_data): receive_dict = json.loads(text_data) message = receive_dict["message"] await self.channel_layer.group_send( self.room_group_name, {"type": "send.message", "message": message} ) async def send_message(self, event): message = event["message"] await self.send(text_data=json.dumps({"message": message}))miaplicación/routing.py
from django.urls import re_path from . import consumers websocket_urlpatterns = [ re_path(r"", consumers.ChatConsumer.as_asgi()), ]Pruebe pip install 'asgiref==3.3.4' .
Noté un RuntimeError: Single thread executor already being used, would deadlock bloquearía después de actualizar de asgiref 3.3.4 a 3.4.1.
Esto parece deberse a un problema actualmente no resuelto en channels 3.0.4 donde las solicitudes simultáneas en el servidor de desarrollo de Django fallan de manera intermitente. Ver también Runtime Error Deadlock que ocurre aleatoriamente en Django .
En 3.4.0, asgiref introdujo verificaciones adicionales de puntos muertos. Eso es algo bueno, pero puede haber expuesto un problema subyacente en los canales. Desde el registro de cambios :
* Calling sync_to_async directly from inside itself (which causes a deadlock when in the default, thread-sensitive mode) now has deadlock detection.