Page 1 of 1
uasyncio - sched module, long delay events.
Posted: Thu Oct 08, 2020 11:16 am
by AndreaC
Hello,
struggling days to understand why a schedule like this (running on a pyboardv1.1 fw:1.13):
Code: Select all
async def mycoro():
print('hello world')
await asyncio.sleep(0)
async def main():
asyncio.create_task(schedule(mycoro, hrs=12))
try:
loop = asyncio.get_event_loop()
loop.create_task(main())
loop.run_forever()
except KeyboardInterrupt:
pass
finally:
asyncio.new_event_loop() # Clear retained state
instead of everyday at 12am launches mycoro approximately every 16mins and 40secs.
Eventually today, looking at schedule coro definition I discovered the clause:
maxt = 1000 # uasyncio can't handle arbitrarily long delays
Onestly I can't figure out how to achive my goal? should the schedule coro return instead of launch the passed function just after 1000secs?
I am missing something?
Hope I explained myself clearly.
Regards
Re: uasyncio - sched module, long delay events.
Posted: Thu Oct 08, 2020 3:19 pm
by AndreaC
AndreaC wrote: ↑Thu Oct 08, 2020 11:16 am
Hello,
struggling days to understand why a schedule like this (running on a pyboardv1.1 fw:1.13):
Code: Select all
async def mycoro():
print('hello world')
await asyncio.sleep(0)
async def main():
asyncio.create_task(schedule(mycoro, hrs=12))
try:
loop = asyncio.get_event_loop()
loop.create_task(main())
loop.run_forever()
except KeyboardInterrupt:
pass
finally:
asyncio.new_event_loop() # Clear retained state
instead of everyday at 12am launches mycoro approximately every 16mins and 40secs.
Eventually today, looking at schedule coro definition I discovered the clause:
maxt = 1000 # uasyncio can't handle arbitrarily long delays
Onestly I can't figure out how to achive my goal? should the schedule coro return instead of launch the passed function just after 1000secs?
I am missing something?
Hope I explained myself clearly.
Regards
I have apparently by-passed the problem by modifying the schedule function in order to wait until its time to launch the func, but I am still not sure if my approach is correct.
Code: Select all
async def schedule(func, *args, times=None, **kwargs):
fcron = cron(**kwargs)
maxt = 1000 # uasyncio can't handle arbitrarily long delays
while times is None or times > 0:
tw = fcron(int(time())) # Time to wait (s)
while tw > 0: # While there is still time to wait
# *** Added a new variable here tw_***
tw_ = min(tw, maxt)
await asyncio.sleep(tw_)
tw -= tw_
res = launch(func, args)
if times is not None:
times -= 1
await asyncio.sleep_ms(1200) # ensure we're into next second
return res
Re: uasyncio - sched module, long delay events.
Posted: Fri Oct 09, 2020 10:19 am
by pythoncoder
See
my scheduling module which allows
uasyncio tasks to be scheduled over very long periods.
As a general point there is normally no point in using
micropython.schedule() with
uasyncio. Its purpose is to be called from interrupt service routines.
The
uasyncio way is for a coroutine to pause for a period, then trigger the task with
asyncio.create_task(). However the way that
uasyncio implements
sleep() and
sleep_ms() means there is an upper limit to the delay. My schedule module overcomes this limitation.
Re: uasyncio - sched module, long delay events.
Posted: Fri Oct 09, 2020 12:24 pm
by AndreaC
Thank you Peter, but the point is that I am indeed talking about your schedule module not the micropython.schedule().
Code: Select all
# sched.py
# Copyright (c) 2020 Peter Hinch
# Released under the MIT License (MIT) - see LICENSE file
import uasyncio as asyncio
from sched.primitives import launch
from time import time
from sched.cron import cron
async def schedule(func, *args, times=None, **kwargs):
fcron = cron(**kwargs)
maxt = 1000 # uasyncio can't handle arbitrarily long delays
while times is None or times > 0:
tw = fcron(int(time())) # Time to wait (s)
while tw > 0: # While there is still time to wait
tw = min(tw, maxt)
await asyncio.sleep(tw)
tw -= maxt
res = launch(func, args)
if times is not None:
times -= 1
await asyncio.sleep_ms(1200) # ensure we're into next second
return res
For what I can see, if the value returned by the cron object
Code: Select all
tw = fcron(int(time())) # Time to wait (s)
is greater than 1000 as in my case, the schedule coro according to
Code: Select all
while tw > 0: # While there is still time to wait
tw = min(tw, maxt)
await asyncio.sleep(tw)
tw -= maxt
res = launch(func, args)
will launches de func at the 1000th second, so I can not figure out how it can deal with long delays?
Re: uasyncio - sched module, long delay events.
Posted: Sat Oct 10, 2020 9:26 am
by pythoncoder
Ah, sorry about the misunderstanding.
You have indeed found a howler of a bug in my code.
[EDIT]
I have pushed an update. This is my fix:
Code: Select all
async def schedule(func, *args, times=None, **kwargs):
fcron = cron(**kwargs)
maxt = 1000 # uasyncio can't handle arbitrarily long delays
while times is None or times > 0:
tw = fcron(int(time())) # Time to wait (s)
while tw > 0: # While there is still time to wait
await asyncio.sleep(min(tw, maxt)) # Never wait longer than maxt
tw -= maxt
res = launch(func, args)
if times is not None:
times -= 1
await asyncio.sleep_ms(1200) # ensure we're into next second
return res
I have modified your test script to make it more compliant with the V3 way of doing things (not that this has anything to do with the bug).
Code: Select all
import uasyncio as asyncio
from sched.primitives import launch
from time import localtime
from sched.sched import schedule
async def mycoro():
print('hello world')
yr, mo, md, h, m, s, wd = localtime()[:7] # Provide confirmation of when it ran
fst = 'Callback {:02d}:{:02d}:{:02d} on {:02d}/{:02d}/{:02d}'
print(fst.format(h, m, s, md, mo, yr))
await asyncio.sleep(0)
async def main():
asyncio.create_task(schedule(mycoro, hrs=11))
while True:
await asyncio.sleep(100) # Keep the scheduler running forever
try:
asyncio.run(main()) # This has superseded the event loop stuff
finally:
asyncio.new_event_loop() # Clear retained state
Re: uasyncio - sched module, long delay events.
Posted: Sat Oct 10, 2020 11:59 am
by AndreaC
Thanks Peter, especially for the valuable advice on my code. I would like to congratulate you for the amazing work you did with the uasyncio tutorial. Since I discovered the existence of uasyncio I completely rewrote the code of my project which was previously based on threads. Now I have no more problems regarding the heap fragmentation.