I ran into a bizarre issue while trying to structure my code as follows:
At the beginning, the program starts n multi timers that repeatedly call methods m_1 to m_n every t_1 to t_n seconds.
To implement this, I use the MultiTimer library (https://pypi.org/project/multitimer/). For flexibility I define a named tuple at the start of the program that contains the method, whether or not it is enabled and the frequency with which it should be called.
I assume the issue is in how I use the named tuple, but I can’t seem to figure out what the problem is.
BotSettings = namedtuple(
"BotSettings", ["method", "enabled", "repeat_every_x_seconds"])
bot_list = [
BotSettings(method=bots.accept_pending_invites,
enabled=True, repeat_every_x_seconds=10),
BotSettings(method=bots.handle_cat_requests,
enabled=True, repeat_every_x_seconds=10),
BotSettings(method=bots.handle_confession_requests,
enabled=True, repeat_every_x_seconds=10)
]
timers = [MultiTimer(bot.repeat_every_x_seconds, lambda: bot.method(
client), runonstart=True) for bot in bot_list if bot.enabled]
for timer in timers:
timer.start()
The output of the above program is as follows:
handle confession requests called handle confession requests called handle confession requests called
Another observation I made is that the program always calls the last method in bot_list num_enabled times where num_enabled is the number of methods in bot_list with enabled=True.
Advertisement
Answer
Replace the lambda with function and pass arguments using kwargs. I used this code to test.
from multitimer import MultiTimer
def accept_pending_invites(client): print('invite', client)
def handle_cat_requests(client): print('cat', client)
def handle_confession_requests(client): print('confess', client)
bot_list=[
{ 'method':accept_pending_invites, 'enabled':True, 'repeat_every_x_seconds':10},
{ 'method':handle_cat_requests,'enabled':True, 'repeat_every_x_seconds':10},
{ 'method':handle_confession_requests, 'enabled':True, 'repeat_every_x_seconds':10}
]
timers = [MultiTimer(bot['repeat_every_x_seconds'], function=bot['method'], runonstart=True, kwargs={'client':123}) for bot in bot_list]
for timer in timers:
timer.start()
Output
invite 123 cat 123 confess 123