如何使用asyncio在每分钟整点重复运行多参数异步函数?
用asyncio实现每分钟整点永久重复执行多参数函数
我来帮你搞定这个问题!你已经摸到了asyncio的门儿,差的就是把单次调度改成永久循环调度的逻辑——asyncio.call_at()完全能做到这件事,核心思路就是:每次任务执行完毕后,计算出下一个整点的时间,然后递归调度自己,形成循环。
核心实现思路
- 并行执行多参数任务:用
asyncio.gather()把所有带不同参数的函数打包成一个协程组,确保它们在整点同时启动。 - 计算下一个整点时间:根据当前时间,算出距离下一分钟整的秒数,转换为asyncio事件循环能识别的时间戳。
- 递归调度:任务执行完成后,用
call_at()调度下一次的执行,实现永久循环。
完整代码示例
import asyncio from datetime import datetime, timedelta # 你的带参数业务函数示例 async def your_business_task(param1, param2): print(f"[{datetime.now().strftime('%H:%M:%S')}] 执行任务 | 参数: {param1}, {param2}") # 替换成你的实际业务逻辑,比如API调用、数据处理等 await asyncio.sleep(0.5) # 模拟任务耗时 async def scheduled_job(loop): """调度所有任务,并递归安排下一次执行""" # 1. 并行执行所有带不同参数的任务 await asyncio.gather( your_business_task("用户A", "订单1001"), your_business_task("用户B", "订单1002"), your_business_task("用户C", "订单1003") ) # 2. 计算下一个整点的时间(比如当前19:00:23,下一个就是19:01:00) now = datetime.now() # 计算距离下一分钟整的秒数,避免刚好整点时的误差 seconds_to_next_minute = 60 - now.second if seconds_to_next_minute == 60: seconds_to_next_minute = 0 next_run_time = now + timedelta(seconds=seconds_to_next_minute) # 3. 转换为asyncio事件循环的时间戳格式(loop.time()返回的是相对于事件循环启动后的秒数) next_run_timestamp = loop.time() + (next_run_time - now).total_seconds() # 4. 递归调度下一次任务,用lambda包装确保协程被正确创建 loop.call_at(next_run_timestamp, lambda: asyncio.create_task(scheduled_job(loop))) async def main(): loop = asyncio.get_running_loop() # 计算第一次执行的时间:立即调度到下一个整点 now = datetime.now() seconds_to_first_run = 60 - now.second if seconds_to_first_run == 60: seconds_to_first_run = 0 first_run_timestamp = loop.time() + seconds_to_first_run # 启动第一次调度 loop.call_at(first_run_timestamp, lambda: asyncio.create_task(scheduled_job(loop))) # 让事件循环一直运行(用Event阻塞,直到手动终止) await asyncio.Event().wait() if __name__ == "__main__": try: asyncio.run(main()) except KeyboardInterrupt: print("程序已终止")
关键细节说明
- 并行执行:
asyncio.gather()会让所有任务同时启动,如果你的任务需要串行执行,把gather换成依次await每个任务即可。 - 时间计算精度:通过
now.second计算等待秒数,能精准对齐到每分钟的00秒位置,避免累积误差。 - 容错处理:如果某个任务执行时间超过一分钟(比如跑了70秒),下一次调度会在任务完成后立刻计算下一个整点(比如这次19:00:00开始,19:01:10结束,下一次会调度到19:02:00)。如果需要严格整点执行(哪怕上一次任务超时),可以修改时间计算逻辑为直接取
datetime(now.year, now.month, now.day, now.hour, now.minute + 1)。
运行效果
启动程序后,你会看到类似这样的输出,每分钟整点准时执行:
[19:00:00] 执行任务 | 参数: 用户A, 订单1001 [19:00:00] 执行任务 | 参数: 用户B, 订单1002 [19:00:00] 执行任务 | 参数: 用户C, 订单1003 [19:01:00] 执行任务 | 参数: 用户A, 订单1001 [19:01:00] 执行任务 | 参数: 用户B, 订单1002 [19:01:00] 执行任务 | 参数: 用户C, 订单1003 ...
内容的提问来源于stack exchange,提问作者jbssm
相关产品推荐
相关产品推荐

