0

I am trying to understand the behavior of the code below. I tried to register a callback function trampoline to be called in an event loop using asyncio module. The trampoline got itself is called multiple times, which I am sure why that happened please. My expectation was the callback trampoline will call itself only once later after 0.5 seconds?

import asyncio import datetime loop = asyncio.get_event_loop() def print_date(): print(datetime.datetime.now()) def trampoline(name: str = "") -> None: print("name:", end=" ") print_date() loop.call_later(0.5, trampoline, name) loop.call_soon(trampoline()) loop.call_later(8, loop.stop) loop.run_forever() 

Output: I also have an exception, which also I am not sure about:

name: 2022-11-11 16:29:04.335313 Exception in callback None() handle: <Handle> Traceback (most recent call last): File "C:\Anaconda3\lib\asyncio\events.py", line 81, in _run self._context.run(self._callback, *self._args) TypeError: 'NoneType' object is not callable name: 2022-11-11 16:29:04.850481 name: 2022-11-11 16:29:05.363303 name: 2022-11-11 16:29:05.872649 name: 2022-11-11 16:29:06.383004 name: 2022-11-11 16:29:06.898766 name: 2022-11-11 16:29:07.413907 name: 2022-11-11 16:29:07.915795 name: 2022-11-11 16:29:08.428609 name: 2022-11-11 16:29:08.939604 name: 2022-11-11 16:29:09.454111 name: 2022-11-11 16:29:09.966438 name: 2022-11-11 16:29:10.470832 name: 2022-11-11 16:29:10.981675 name: 2022-11-11 16:29:11.496746 name: 2022-11-11 16:29:12.011841 Process finished with exit code 0 
3
  • 1
    "My expectation was the callback trampoline will call itself only once later after 0.5 seconds". Yes, and what happens when that second call to trampoline takes place? Commented Nov 11, 2022 at 21:40
  • 1
    I guess you don‘t want to call trampoline() but instead pass the function? Commented Nov 11, 2022 at 21:42
  • 1
    @tfeldmann so you're saying it should just be loop.call_soon(trampoline) right? Commented Nov 11, 2022 at 21:55

1 Answer 1

1

The issue is that trampoline schedules a callback to itself when called.

That means that trampoline will be called after 0.5 seconds, rescheduling again a callback to itself for 0.5 seconds later

To have it only called once, you should remove .call_later from inside trampoline and move it outside:

... def trampoline(name: str = "") -> None: print("name:", end=" ") print_date() loop.call_later(0.5, trampoline) ... 

The exception is due to calling .call_soon with trampoline() (the return value: None) instead of trampoline (the function itself)

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you. Why it does stop though after some calls? In the code, loop.run_forever() was used, so should not trampoline() run forever?
I guess it's because we call loop.call_later(8, loop.stop) that will stop the event loop.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.