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