如何在指定* args或** kwargs

时间:2019-04-07 13:02:33

标签: python function dictionary python-asyncio

我基本上想运行从功能字典收集的任务。我在程序中使用了asyncio,但这对我的问题可能并不重要。这是我的代码来说明...

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()

这很好。但是我想定期重复执行某些任务,因此我向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)

这通过向kwarg interval提供一个整数来使函数重复。将来的功能可能还会使用其他* args和** kwargs。

所以我基本上希望我可以在任务列表字典中指定重复间隔,例如

    tasklist = {
    'Task-1': faketask,
    'Task-2': faketask,
    'Task-3': faketask(interval=60),
    }

但这不起作用,因为 faketask()缺少1个必需的位置参数:'taskname'。

有什么聪明的方法可以解决这个问题吗?

作为一个奖励问题,行_tasks.append(asyncio.ensure_future(tasklist[taskname](taskname)))看起来有点难看,是否有任何方法可以自动传递taskname参数?

1 个答案:

答案 0 :(得分:3)

您可以使用functools.partial,它是专门为以下情况而设计的:

'Task-3': functools.partial(faketask, interval=60),
  

还有一个问题,_tasks.append(asyncio.ensure_future(tasklist[taskname](taskname)))行看起来有点难看,有什么方法可以自动传递taskname参数吗?

您可以使用items()删除冗余:

tasks = []
for taskname, taskfn in tasklist.items():
    tasks.append(taskfn(taskname))

不需要显式调用asyncio.ensure_future,因为asyncio.gather是自动执行的。另外,我将_tasks重命名为tasks。按照惯例,变量名前面的_表示该变量将不会在后续代码中使用,在这里不是这种情况。