0

Can someone give me a tip on how to (understand asnycio) use asnycio to do this:

  1. on_start - method run only once when script starts
  2. get_sensor_readings - method run while event is True
  3. evauluate_data - method run while event is True
  4. check_time - method run while event is True to see if the event is still True
  5. on_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?

3
  • I guess the method check_time should set the attribute event_has_expired = True Commented Jun 4, 2022 at 18:25
  • Would you have any tips on how to implement that? Commented Jun 4, 2022 at 19:16
  • Would I want to implement task.cancel() like this in the SO post? stackoverflow.com/questions/40016501/… Commented Jun 4, 2022 at 19:17

2 Answers 2

1

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() 
Sign up to request clarification or add additional context in comments.

Comments

0

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.

1 Comment

I put an answer in that appears to work but a little unsure about how asnycio works...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.