Skip to content

Instantly share code, notes, and snippets.

@akaIDIOT
Created March 26, 2015 21:26
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save akaIDIOT/48c2474bd606cd2422ca to your computer and use it in GitHub Desktop.
Save akaIDIOT/48c2474bd606cd2422ca to your computer and use it in GitHub Desktop.
Call something periodically using asyncio
import asyncio
def call_periodic(interval, callback, *args, **kwargs):
# get loop as a kwarg or take the default one
loop = kwargs.get('loop') or asyncio.get_event_loop()
# record the loop's time when call_periodic was called
start = loop.time()
def run(handle):
# XXX: we could record before = loop.time() and warn when callback(*args) took longer than interval
# call callback now (possibly blocks run)
callback(*args)
# reschedule run at the soonest time n * interval from start
# re-assign delegate to the new handle
handle.delegate = loop.call_later(interval - ((loop.time() - start) % interval), run, handle)
class PeriodicHandle: # not extending Handle, needs a lot of arguments that make no sense here
def __init__(self):
self.delegate = None
def cancel(self):
assert isinstance(self.delegate, asyncio.Handle), 'no delegate handle to cancel'
self.delegate.cancel()
periodic = PeriodicHandle() # can't pass result of loop.call_at here, it needs periodic as an arg to run
# set the delegate to be the Handle for call_at, causes periodic.cancel() to cancel the call to run
periodic.delegate = loop.call_at(start + interval, run, periodic)
# return the 'wrapper'
return periodic
if __name__ == '__main__':
import sys
loop = asyncio.get_event_loop()
# print loop's time every sys.argv[1] seconds
handle = call_periodic(float(sys.argv[1]),
lambda x: print('{} at {}'.format(x, loop.time()), flush=True),
'Hello, world!') # arg x to lambda
# stop the loop after 10 seconds ...
loop.call_later(10, lambda: loop.stop())
# ... but cancel the periodic call before that to check if cancel() works
loop.call_later(8, lambda: handle.cancel())
loop.run_forever()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment