[英]How to run functions from a dict of functions while specifying *args or **kwargs
I basically want to run tasks that are gathered from a dict of functions. 我基本上想运行从功能字典收集的任务。 I'm using asyncio in my program but it probably doesn't matter for my question. 我在程序中使用了asyncio,但这对我的问题可能并不重要。 Here is my code to illustrate... 这是我的代码来说明...
import asyncio
import random
async def faketask(taskname): # This is a function to simulate asynchronous tasks being performed.
fakedelay = random.randint(1,6)
print(f'{taskname} started (completing in {fakedelay} seconds)')
await asyncio.sleep(fakedelay)
print(f'{taskname} completed after {fakedelay} seconds')
async def main():
tasklist = { # This is a dict of tasks to be performed
'Task-1': faketask,
'Task-2': faketask,
'Task-3': faketask,
}
_tasks = []
for taskname in tasklist:
_tasks.append(asyncio.ensure_future(tasklist[taskname](taskname)))
print(f'Added {taskname} to job queue.')
await asyncio.gather(*_tasks)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()
This works pretty well. 效果很好。 But I want to repeat certain tasks periodically, so I added some code to the faketask
function. 但是我想定期重复执行某些任务,因此我向faketask
函数添加了一些代码。
async def faketask(taskname, interval=None):
fakedelay = random.randint(1,6)
print(f'{taskname} started (completing in {fakedelay} seconds)')
await asyncio.sleep(fakedelay)
print(f'{taskname} completed after {fakedelay} seconds')
if interval is not None:
print(f'Repeating {taskname} in {interval} seconds')
while True:
await faketask(taskname, *args, **kwargs)
await asyncio.sleep(interval)
This makes the function repeat by providing the kwarg interval
with an integer. 通过为kwarg interval
提供一个整数,使函数重复执行。 Future functions may also use additional *args and **kwargs. 将来的功能可能还会使用其他* args和** kwargs。
So I basically wish I could specify the repeat interval in the tasklist dict, eg 所以我基本上希望我可以在任务列表字典中指定重复间隔,例如
tasklist = {
'Task-1': faketask,
'Task-2': faketask,
'Task-3': faketask(interval=60),
}
But that doesn't work because faketask() is missing 1 required positional argument: 'taskname'. 但这是行不通的,因为faketask()缺少1个必需的位置参数:“ taskname”。
Is there any clever way to solve this? 有什么聪明的方法可以解决这个问题吗?
And as a bonus question, the line _tasks.append(asyncio.ensure_future(tasklist[taskname](taskname)))
looks a bit ugly, is there any way to pass the taskname
argument automatically? 作为一个额外的问题, _tasks.append(asyncio.ensure_future(tasklist[taskname](taskname)))
看起来有点难看,有没有办法自动传递taskname
参数?
You can use functools.partial
, which is designed exactly for situations like this: 您可以使用functools.partial
,它是专门为以下情况而设计的:
'Task-3': functools.partial(faketask, interval=60),
And as a bonus question, the line
_tasks.append(asyncio.ensure_future(tasklist[taskname](taskname)))
looks a bit ugly, is there any way to pass the taskname argument automatically? 作为一个额外的问题,_tasks.append(asyncio.ensure_future(tasklist[taskname](taskname)))
看起来有点难看,有没有办法自动传递taskname参数?
You can use items()
to remove the redundancy: 您可以使用items()
删除冗余:
tasks = []
for taskname, taskfn in tasklist.items():
tasks.append(taskfn(taskname))
The explicit call to asyncio.ensure_future
is unnecessary because asyncio.gather
does that automatically. 不需要显式调用asyncio.ensure_future
,因为asyncio.gather
会自动执行此操作。 Also, I've renamed _tasks
to just tasks
. 另外,我改名_tasks
只是tasks
。 By convention, the _
in front of a variable name denotes that the variable will not be used in subsequent code, which is not the case here. 按照惯例,变量名前面的_
表示该变量将不会在后续代码中使用,在这里不是这种情况。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.