asyncio - how to stop background task cleanly
Marko Rauhamaa
marko at pacujo.net
Sat Feb 6 10:34:47 EST 2016
"Frank Millman" <frank at chagford.com>:
> "Marko Rauhamaa" wrote in message news:87lh6ys052.fsf at elektro.pacujo.net...
>> You should
>>
>> await asyncio.wait(..., return_when=asyncio.FIRST_COMPLETED)
>>
>> to deal with multiple alternative stimuli.
>>
>
> Thanks, Marko, that works very well.
>
> [...]
>
> Now I just have one problem left. I will keep experimenting, but if
> someone gives me a hint in the meantime it will be appreciated.
>
> I run my background task like this -
>
> stop_task = False
>
> async def background_task():
> while not stop_task:
> await perform_task()
> await asyncio.sleep(10)
You should set up a separate asyncio.Event or asyncio.Queue to send
"out-of-band" signals to your background_task:
async def background_task(cancel_event):
async def doze_off():
await asyncio.sleep(10)
while True:
await asyncio.wait(
perform_task, cancel_event.wait,
return_when=asyncio.FIRST_COMPETED)
if cancel_event_is_set()
break
await asyncio.wait(
doze_off, cancel_event.wait,
return_when=asyncio.FIRST_COMPETED)
if cancel_event_is_set()
break
That should be the idea, anyway. I didn't try it out.
> I stop the task by setting stop_task to True. It works, but it waits for
> the 10-second sleep to expire before it is actioned.
>
> With threading, I could set up a threading.Event(), call
> evt.wait(timeout=10) to run the loop, and evt.set() to stop it. It
> stopped instantly.
>
> Is there an equivalent in asyncio?
Yes, you could simplify the above thusly:
async def background_task(cancel_event):
while True:
await asyncio.wait(
perform_task, cancel_event.wait,
return_when=asyncio.FIRST_COMPETED)
if cancel_event_is_set()
break
await asyncio.wait(
cancel_event.wait, timeout=10,
return_when=asyncio.FIRST_COMPETED)
if cancel_event_is_set()
break
Marko
More information about the Python-list
mailing list