
本文介绍一种基于贪心轮询策略的python调度算法,用于将多个脚本按指定频次(times_per_min)均匀分布到60秒时间窗内执行,确保同类任务间隔尽可能均衡,且不同任务交错运行。
本文介绍一种基于贪心轮询策略的python调度算法,用于将多个脚本按指定频次(times_per_min)均匀分布到60秒时间窗内执行,确保同类任务间隔尽可能均衡,且不同任务交错运行。
要实现“每分钟执行N次、且各次执行时间尽量等距分布”的调度目标,关键在于避免简单重复拼接任务列表(如 ['test0.sh'] * 3 + ['test1.sh'] * 2),因为这会导致同类任务扎堆,违背“等距”与“交错”要求。
正确的思路是:模拟一个公平的轮询调度器——每次从仍有剩余配额的任务中,优先选择当前累计执行次数最少(或剩余次数最多)的那个,从而天然拉大同类任务的间隔。最简洁高效的实现方式是采用贪心轮询(Round-Robin with remaining quota):
import subprocess
import time
import yaml
# 1. 加载配置
with open("tasks.yaml") as f:
config = yaml.safe_load(f)
tasks = config.get("every_minute", [])
# 2. 构建任务-剩余次数映射
task_quota = {t["path"]: t["times_per_min"] for t in tasks}
# 3. 贪心轮询生成均匀序列
TASKS = []
while any(count > 0 for count in task_quota.values()):
# 遍历所有任务,对仍有余量者各分配一次(保持顺序稳定性)
for path, remaining in list(task_quota.items()):
if remaining > 0:
TASKS.append(path)
task_quota[path] -= 1
# 此时 TASKS = ['test0.sh', 'test1.sh', 'test0.sh', 'test1.sh', 'test0.sh']
print(TASKS) # ✅ 符合期望的交错均匀分布
# 4. 执行调度(每60秒均分间隔)
if TASKS:
interval = 60.0 / len(TASKS)
for task_path in TASKS:
try:
subprocess.Popen([task_path])
print(f"Launched {task_path}")
except Exception as e:
print(f"Failed to launch {task_path}: {e}")
time.sleep(interval)✅ 该算法优势:
-
普适性强:支持任意数量任务及任意
times_per_min组合(包括0、1、大数); - 天然均衡:通过逐轮消耗配额,使高频任务被低频任务“穿插”,最大化最小间隔;
- 确定性高:相同输入总产生相同执行序列,便于测试与复现。
⚠️ 注意事项:
- 若某脚本执行耗时显著(>
interval),后续任务将延迟,建议增加超时控制或改用异步/线程池; - 实际生产环境应添加日志、错误重试、资源监控,并考虑使用
APScheduler或Celery等专业调度框架; -
time.sleep()精度受系统影响,高精度场景需用time.monotonic()校准。
总结:均匀调度的本质不是“平均切分时间”,而是“公平分配机会”。用剩余配额驱动的轮询策略,以极简代码实现了强鲁棒性的任务交错分布,是轻量级定时任务编排的理想解法。

















