Search code examples
pythondjangoceleryworkerchannel

Django - Celery Worker - Channels


thank you in advance

I am trying to start a Celery Worker to accept WebConnections usng Channels - but when my worker starts it cannot seem to find channels. When I pip list channels is installed

settings.py has channels

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'channels','

tasks.py

from __future__ import absolute_import, unicode_literals
import os
import threading
from merlin.celery import app, get_blender
from django.conf import settings
from celery import shared_task
from channels import Channel

@app.task(bind=True, track_started=True)
def render(task, data, reply_channel):
    bpy = get_blender()
    setup_scene(bpy, data)

context = {'rendering': True, 'filepath': os.path.join(settings.BLENDER_RENDER_TMP_DIR, task.request.id)}
sync_thread = threading.Thread(target=sync_render, args=(bpy, context, reply_channel))
sync_thread.start()
bpy.ops.render.render()
context['rendering'] = False
sync_thread.join()

if os.path.exists(context['filepath']):
    os.remove(context['filepath'])

if reply_channel is not None:
    Channel(reply_channel).send({
        'text': json.dumps({
            'action': 'render_finished'
        })
    })'

The error I get -

from channels import Channel
ImportError: cannot import name 'Channel' from 'channels' 
(/usr/local/lib/python3.8/dist-packages/channels/__init__.py)

Again thank you in advance


Solution

  • See the documentation for using channel layers outside of consumers

    from asgiref.sync import async_to_sync
    from channels.layers import get_channel_layer
    channel_layer = get_channel_layer()
    
    @app.task(bind=True, track_started=True)
    def render(task, data, reply_channel):
        ...
        async_to_sync(channel_layer.send)(reply_channel, {
            'type': 'this_is_required',
            'text': json.dumps({
                'action': 'render_finished'
            })
        })
    

    You may want to consider using channel workers and background tasks