3

I have the following function to call s(c) every 24 hours.

def schedule_next_sync(): t = datetime.datetime.now() t = t.replace(hour=0) + datetime.timedelta(hours=24) def wrapper(): s(c) schedule_next_sync() tornado.ioloop.IOLoop.current().add_timeout(datetime.datetime.timestamp(t), wrapper) 

However, s() will be changed to an async function.

async def s(c): 

How to update schedule_next_sync for async function? Should run s() synchronously? Or change schedule_next_sync() to an async function?

5
  • Is there a need of async here ? if we have to call a function periodically then why should i make it asynchronous ? curious to know the use case Commented Nov 18, 2021 at 15:39
  • What's wrong with a simple while loop for if you just want to call ~ every 1 s? Commented Nov 18, 2021 at 15:40
  • @DeepakTripathi, s() will need to call some async functions. Commented Nov 18, 2021 at 21:41
  • @2e0byo, I actually need to schedule it at night everyday. Updated the question. Commented Nov 18, 2021 at 23:15
  • Have you considered the function loop.call_at(timestamp, callback, *args)? In your case, callback could be asyncio.create_task and the only argument would be s(c). Commented Nov 19, 2021 at 2:05

1 Answer 1

1

Once s is async, you could use asyncio.sleep() instead of the lower-level add_timeout():

async def schedule_next_sync(): async def call_forever(): while True: await asyncio.sleep(1) await s(c) tornado.ioloop.IOLoop.current().create_task(call_forever()) 

If you really want to do it with timeouts, something like this should work:

def schedule_next_sync(): t = datetime.datetime.now() + datetime.timedelta(seconds=1) def wrapper(): loop = asyncio.get_running_loop() task = loop.create_task(s(c)) task.add_done_callback(lambda _: schedule_next_sync()) loop = tornado.ioloop.IOLoop.current() loop.add_timeout(datetime.datetime.timestamp(t), wrapper) 
Sign up to request clarification or add additional context in comments.

3 Comments

Actually I will need to schedule the call at a particular time every day so I will need to use the second one. I'm using Python 3.6 so there is no get_running_loop()?
@ca9163d9 Ah, the example in the question was misleading then. You could still use asyncio.sleep() and just calculate the time to sleep until the next event. (To me the sleep version is much more natural.) In Python 3.6 you can just use asyncio.get_event_loop() instead of get_running_loop(), it should return the same thing when called from inside a coroutine or callback. The only difference is that get_running_loop() raises an exception when not called from a coroutine or callback, i.e. it effectively asserts that it's called from an async context.
Sorry, I've updated the question. I actually need to make it run every night. I changed to one second for debugging.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.