Channels worker and call_later

28 views
Skip to first unread message

Ken Whitesell

unread,
Feb 23, 2018, 10:51:25 PM2/23/18
to Django users
TLDR: Is there a way to use the call_later function within a worker task? (Or am I just looking at this issue the wrong way?)

Software - Python 3.6, Django 2.0.2, Channels 2.0.2, trying to run this on either / both Windows 10 and Ubuntu 17.10 if it matters

Longer version - I'm having surprisingly few problems with wrapping my head around the new Channels 2, especially since this is the first I've been using asyncio and it's been about 10 years since I've used Twisted. All my personal sample code that I've been trying to write has been working great.

Except... I have the situation where I want to schedule an event for some fixed period of time in the future - say 30 seconds.
But, it's also necessary for me to be able to cancel that scheduled event.

I've tried a number of different combinations for the worker task between SyncConsumer and AsyncConsumer, and different combinations of async and regular methods, and get a variety of different errors. But the bottom line is that I haven't stumbled across the magic sauce that will let this work.

I _can_ get the delay to work by using the asyncio.sleep method, using the pattern shown in the "Delay server" paragraph in the "What's new in Channels 2?" section of the docs. But while that method (sleep) returns a generator object, I don't see where that does me any good with trying to cancel that sleep.

I know I can make this work by setting some variable, and check that after the sleep has finished to determine whether or not I still need to do my work, but that just "feels wrong" to me for some reason.

Is there something simple that I'm missing? Or does this fit into the category of "Don't do that!"

Thanks,
     Ken

Andrew Godwin

unread,
Feb 23, 2018, 10:56:03 PM2/23/18
to django...@googlegroups.com
Hi Ken,

You should write asyncio code, rather than Twisted code - we have Twisted running on it asyncio reactor so both are available, and asyncio is the only thing you're guaranteed from the spec/other future servers.

Given that, I would recommend making a separate asyncio Task that has an "await asyncio.sleep(30)" in it and then does what you want. If you then need to cancel the task, you can call ".cancel()" on it (and remember, you can put it on `self` if you need to keep a reference).

To make a task, just do:

loop = asyncio.get_event_loop()
self.task = loop.create_task(coroutine_function())

Hope that helps!

Andrew

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/642da2f0-5c07-44ee-9059-a366ef67de14%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Ken Whitesell

unread,
Feb 23, 2018, 11:23:41 PM2/23/18
to Django users
Andrew,

     Thanks for the quick reply! Yea, I kinda guessed I was overthinking this. Your solution works 100% for exactly what I'm trying to do.

Sorry about the confusion regarding my reference to Twisted, it's no part of this particular project - I only mentioned it to state that while it has been awhile, I do have some familiarity with (in a general sense) asynchronous / event-driven programming in Python, but no specific knowledge of the current asyncio in Python 3.6 - so while I'm comfortable with the general concepts, there are a lot of the specifics that I'm still picking up.

Anyway, thanks again!

Ken 


On Friday, February 23, 2018 at 10:56:03 PM UTC-5, Andrew Godwin wrote:
Hi Ken,

You should write asyncio code, rather than Twisted code - we have Twisted running on it asyncio reactor so both are available, and asyncio is the only thing you're guaranteed from the spec/other future servers.

Given that, I would recommend making a separate asyncio Task that has an "await asyncio.sleep(30)" in it and then does what you want. If you then need to cancel the task, you can call ".cancel()" on it (and remember, you can put it on `self` if you need to keep a reference).

To make a task, just do:

loop = asyncio.get_event_loop()
self.task = loop.create_task(coroutine_function())

Hope that helps!

Andrew
On Fri, Feb 23, 2018 at 7:48 PM, Ken Whitesell <kenwhi...@comcast.net> wrote:
TLDR: Is there a way to use the call_later function within a worker task? (Or am I just looking at this issue the wrong way?)

Software - Python 3.6, Django 2.0.2, Channels 2.0.2, trying to run this on either / both Windows 10 and Ubuntu 17.10 if it matters

Longer version - I'm having surprisingly few problems with wrapping my head around the new Channels 2, especially since this is the first I've been using asyncio and it's been about 10 years since I've used Twisted. All my personal sample code that I've been trying to write has been working great.

Except... I have the situation where I want to schedule an event for some fixed period of time in the future - say 30 seconds.
But, it's also necessary for me to be able to cancel that scheduled event.

I've tried a number of different combinations for the worker task between SyncConsumer and AsyncConsumer, and different combinations of async and regular methods, and get a variety of different errors. But the bottom line is that I haven't stumbled across the magic sauce that will let this work.

I _can_ get the delay to work by using the asyncio.sleep method, using the pattern shown in the "Delay server" paragraph in the "What's new in Channels 2?" section of the docs. But while that method (sleep) returns a generator object, I don't see where that does me any good with trying to cancel that sleep.

I know I can make this work by setting some variable, and check that after the sleep has finished to determine whether or not I still need to do my work, but that just "feels wrong" to me for some reason.

Is there something simple that I'm missing? Or does this fit into the category of "Don't do that!"

Thanks,
     Ken

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages