'Python asyncio sleep not wakes up
I am trying yo have a progress indicator where one task is doing something while the other indicates a progress. My hello world version of this things goes to sleep in one of the tasks but never wakes up.
What am I missing?
Thanks a lot
import asyncio
import sys
import time
import itertools
progress = True
def get_progress():
return progress
async def define_progress():
print("progress started")
await asyncio.sleep(2)
progress = False
print("progress ended")
async def run_spinner(msg):
spinner = itertools.cycle(['-', '/', '|', '\\'])
sys.stdout.write("{0} ".format(msg))
while(get_progress()):
sys.stdout.write("{0}".format(next(spinner)))
sys.stdout.flush()
time.sleep(0.3)
sys.stdout.write('\b')
async def main():
msg = "start logic"
await asyncio.gather(run_spinner(msg), define_progress())
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(main())
finally:
loop.close()
The output looks like below while the second line infinitely run the spinner.
progress started
creating package\
Solution 1:[1]
I had to make progress a global variable and add await asyncio.sleep(1) to run_spinner. I'm not sure this answers your question, but it does seem to do what you wanted.
import asyncio
import sys
import time
import itertools
global progress
progress = True
def get_progress():
global progress
return progress
async def define_progress():
global progress
print("progress started")
await asyncio.sleep(2)
progress = False
print("progress ended")
async def run_spinner(msg):
spinner = itertools.cycle(['-', '/', '|', '\\'])
sys.stdout.write("{0} ".format(msg))
while(get_progress()):
sys.stdout.write("{0}".format(next(spinner)))
sys.stdout.flush()
time.sleep(0.2)
sys.stdout.write('\b')
await asyncio.sleep(1)
async def main():
msg = "start logic"
await asyncio.gather(run_spinner(msg), define_progress())
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(main())
finally:
loop.close()
Solution 2:[2]
- The
run_spinner
coroutine is missing anawait asyncio.sleep(0)
to give the other taskdefine_progress
some processing time. - The
progress = False
instruction in thedefine_progress
task creates a local variable which shadows the global variable of the same name. Therefor, even if thedefine_progress
finishes, therun_spinner
will continue as it reads the global which is stillTrue
.
Remarks: From https://docs.python.org/3.9/library/asyncio-task.html#sleeping
sleep() always suspends the current task, allowing other tasks to run.
Setting the delay to 0 provides an optimized path to allow other tasks to run. This can be used by long-running functions to avoid blocking the event loop for the full duration of the function call.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | REXXman |
Solution 2 | avans |