Can someone give me a tip on how to (understand asnycio) use asnycio to do this:
on_start
- method run only once when script startsget_sensor_readings
- method run while event is Trueevauluate_data
- method run while event is Truecheck_time
- method run while event is True to see if the event is still Trueon_end
- method run only once when event has expired before script ends
This script below works, just simulating how long the method will execute I used random
package await asyncio.sleep(random.randint(3, 9))
just to add some randomness for the bullet points above 2,3,4.
import asyncio
from datetime import datetime as dt
from datetime import timedelta as td
import random
import time
class Program:
def __init__(self):
self.duration_in_seconds = 60
self.program_start = dt.now()
self.event_has_expired = False
async def on_start(self):
print("On Start Event Start! Applying Overrides!!!")
await asyncio.sleep(random.randint(3, 9))
async def on_end(self):
print("On End Releasing All Overrides!")
await asyncio.sleep(random.randint(3, 9))
async def get_sensor_readings(self):
print("getting sensor readings!!!")
await asyncio.sleep(random.randint(3, 9))
async def evauluate_data(self):
print("checking data!!!")
await asyncio.sleep(random.randint(3, 9))
async def check_time(self):
if (dt.now() - self.program_start > td(seconds = self.duration_in_seconds)):
self.event_has_expired = False
print("Event is DONE!!!")
else:
print("Event is not done! ",dt.now() - self.program_start)
async def main(self):
# script starts, do only once self.on_start()
await self.on_start()
print("On Start Done!")
while not self.event_has_expired:
await self.get_sensor_readings()
await self.evauluate_data()
await self.check_time()
# script ends, do only once self.on_end() when even is done
await self.on_end()
print('Done Deal!')
async def main():
program = Program()
await program.main()
asyncio.run(main())
What I notice is the scripts still keeps running
On Start Event Start! Applying Overrides!!!
going into event intermission mode
getting sensor readings!!!
checking data!!!
Event is not done! 0:00:23.131918
getting sensor readings!!!
checking data!!!
Event is not done! 0:00:31.211425
getting sensor readings!!!
checking data!!!
Event is not done! 0:00:43.272416
getting sensor readings!!!
checking data!!!
Event is not done! 0:00:52.362870
getting sensor readings!!!
checking data!!!
Event is DONE!!!
getting sensor readings!!!
checking data!!!
Event is DONE!!!
getting sensor readings!!!
checking data!!!
Event is DONE!!!
getting sensor readings!!!
checking data!!!
Any tips greatly appreciated. How do I cancel
coroutines when the Event is DONE
and then move into running the on_end
method only once before the script ends?
CodePudding user response:
This appears to work:
import asyncio
from datetime import datetime as dt
from datetime import timedelta as td
import random
import time
class Program:
def __init__(self):
self.duration_in_seconds = 20
self.program_start = dt.now()
self.event_has_expired = False
self.canceled_success = False
async def on_start(self):
print("On Start Event Start! Applying Overrides!!!")
await asyncio.sleep(random.randint(3, 9))
async def on_end(self):
print("On End Releasing All Overrides!")
await asyncio.sleep(random.randint(3, 9))
async def get_sensor_readings(self):
print("getting sensor readings!!!")
await asyncio.sleep(random.randint(3, 9))
async def evauluate_data(self):
print("checking data!!!")
await asyncio.sleep(random.randint(3, 9))
async def check_time(self):
if (dt.now() - self.program_start > td(seconds = self.duration_in_seconds)):
self.event_has_expired = True
print("Event is DONE!!!")
else:
print("Event is not done! ",dt.now() - self.program_start)
async def main(self):
# script starts, do only once self.on_start()
await self.on_start()
print("On Start Done!")
while not self.canceled_success:
readings = asyncio.ensure_future(self.get_sensor_readings())
analysis = asyncio.ensure_future(self.evauluate_data())
checker = asyncio.ensure_future(self.check_time())
if not self.event_has_expired:
await readings
await analysis
await checker
else:
# close other tasks before final shutdown
readings.cancel()
analysis.cancel()
checker.cancel()
self.canceled_success = True
print("cancelled hit!")
# script ends, do only once self.on_end() when even is done
await self.on_end()
print('Done Deal!')
async def main():
program = Program()
await program.main()
CodePudding user response:
Debugging nit: prior to await self.on_end()
you should print
something.
Doesn't matter for this question, as apparently we never get that far.
You believe that check_time changed self.event_has_expired
,
yet the while
loop doesn't see it change.
I am reading the documentation.
It suggests using a synchronization primitive such as a condition variable from the threading or perhaps from the asyncio libraries.
But now as I read the comments,
I see that @svex99 correctly diagnosed the trouble -- you initialize
the variable to False
and then upon "change" you again make it False
.
So of course the while
loop will never terminate.
Let us know how testing goes once you adjust that detail.