脚本中自定义了多个非阻塞型函数,这些函数有的需要每1秒执行一次,有的需要每2秒,或自定义的周期来执行。具体函数的调用周期标明在其函数名上,如函数名“job_4_cycle_seconds_1”的含义是job_4以每1秒钟一次的周期调用。
以下为实现该场景的脚本框架:
import threading
import types
import re
import time
from functools import reduce
import math
from collections import defaultdict
from threading import Event
import signal
run_event = Event()
def on_kill(signum, frame):
run_event.set()
print("finish")
def lcm(a, b):
return abs(a*b) // math.gcd(a, b)
def lcm_multiple(numbers):
return reduce(lcm, numbers)
def job_1_cycle_seconds_1():
print(f"job 1")
def job_4_cycle_seconds_1():
print(f"job 4")
def job_2_cycle_seconds_2():
print(f"job 2")
def job_5_cycle_seconds_2():
print(f"job 5")
def job_3_cycle_seconds_5():
print(f"job 3")
def job_6_cycle_seconds_7():
print(f"job 6")
def xx_1():
print(f"nothing")
def xx_2():
print(f"nothing")
def main_loop(cycle_jobs_dict: dict):
clock = 1
time_step_seconds = 1
cycle_max_seconds = lcm_multiple(list(cycle_jobs_dict.keys()))
print("start")
while not run_event.is_set():
for cycle, jobs in cycle_jobs_dict.items():
if clock % cycle == 0:
for job in jobs:
job()
clock = (clock + 1) % cycle_max_seconds
time.sleep(time_step_seconds)
if __name__ == "__main__":
signal.signal(signal.SIGINT, on_kill)
signal.signal(signal.SIGTERM, on_kill)
cycle_jobs = defaultdict(list)
current_module = globals()
functions = {name: obj for name, obj in current_module.items()
if isinstance(obj, types.FunctionType)}
cycle_seconds_pattern = r'cycle_seconds_(\d+)'
for function_name, function_obj in functions.items():
cycle_time = re.findall(cycle_seconds_pattern, function_name)
if cycle_time:
cycle_time = int(cycle_time[0])
cycle_jobs[cycle_time].append(function_obj)
main_loop(cycle_jobs)