Issue
So I have been trying to run two functions simultaneously but one never seems to work unless I stop the other. The first function is intended to send an email every 30 seconds(function tested by itself and it works) the second is to print a simple statement every 5 seconds. So after every 6 "Hello Worlds" statements I see, I should get an email. However, I never end up getting an email unless I implement something in the run function to stop it like "end after 10 seconds". I wish to have both functions continue infinitely(without crashing if possible). Any help is appreciated.
async def timer():
now = time.time()
end = now + 30
#sendmail(name, filepath + "\\" + name, receiver)
while True:
if time.time() >= end:
sendmail(name, filepath + "\\" + name, receiver)
now = time.time()
end = now + 30
async def runs():
while True:
print("Hello World")
time.sleep(5)
loop = asyncio.get_event_loop()
loop.create_task(runs())
loop.create_task(timer())
loop.run_forever()
Also if anyone if able to complete the task using the multiprocessing or threading module I would be interested to see how it is done as I have tried and failed with both. sample of what I tried:
t1 = threading.Thread(target=timer)
t2 = threading.Thread(target=runs)
t1.start()
t2.start()
Solution
Python's async
coroutines are meant for cooperative concurrency. That means that coroutines must actively allow others to run. For simple cases, use await asyncio.sleep
to pause the current coroutine and run others.
async def timer():
while True:
await asyncio.sleep(30)
sendmail(name, filepath + "\\" + name, receiver)
async def runs():
while True:
print("Hello World")
await asyncio.sleep(5)
async def main():
await asyncio.gather(timer(), runs())
asyncio.run(main())
Notably, do not use time.sleep
– this blocks the entire thread, meaning the current coroutine as well as the event loop and all other coroutines.
Similarly, avoid any synchronous code with significant runtime – asyncio
cannot switch to other coroutines while synchronous code runs. If needed, use an asyncio
helper to run synchronous code in a thread, e.g. asyncio.to_thread
or loop.run_in_executor
.
async def timer():
next_run = time.time()
while True:
# run blocking function in thread to keep event-loop free
await asyncio.to_thread(sendmail, name, filepath + "\\" + name, receiver)
# pause to run approx every 30 seconds
await asyncio.sleep(next_run - time.time())
next_run += 30
Answered By - MisterMiyagi
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.