首页 > 解决方案 > 是否有 Python 库或解决方案可以在一分钟或一小时内执行?

问题描述

我的目标是在不同的计算机上运行一个程序并从测量中获取数据。问题是这些测量需要同时发生(尽可能)。我目前的方法是安装 crony 以同步所有机器的时间并启动一个 python 程序,该程序将在每分钟开始时进行测量。事实证明这非常笨拙,因为我必须循环轮询 time.time() 并检查我们是否进入了新的分钟。

time_factor = 1   # 1000 if desired resolution is ms, 1 if seconds
interval_s = 60 * time_factor
old_interval = int(time.time()*time_factor) / interval_s
current_interval = None
running = True
while running:
    t_s = int(time.time() * time_factor)
    current_interval = t_s / interval_s

    if (t_s % interval_s == 0) and (current_interval != old_interval):
        request_runtime = time.time()

        await self.do_time_sensitive_work()

        old_interval = current_interval
        request_runtime = time.time() - request_runtime
        await asyncio.sleep(int(interval_s - request_runtime - 1))
    else:
        await asyncio.sleep(0.01)

这类问题是否有标准解决方案,或者至少有更优雅的解决方案?

标签: pythontimeruntimepython-asynciointervals

解决方案


我尝试使用apscheduler库,因为它似乎实现了一个 cron 表达式,但是我发现这种方法有两个缺点。一种是库与 asyncio 代码非常奇怪地集成,一定是我的实现的错误。第二个问题是计划任务实际开始运行需要几毫秒,这是一个小问题,但是手动调度可以避免这种滞后,我希望尽可能接近“准确时间”

我也尝试过使用celery beat,但这似乎有点过头了,必须安装 Redis 或其他东西作为消息代理,并且使用如此复杂的框架来完成如此小的任务只会尖叫“错误”。

当前运行速度足够快的解决方案依赖于使用“time_factor”修改时间检查的分辨率,以秒为单位修改 time.time() 值。解决方案的主要部分是将当前时间除以间隔,以获得历史间隔的亲切数字,如果这个数字改变了,我们就输入新的间隔:

time_factor = 100  # 1000 for milliseconds
interval_size = 60 * time_factor
sleep_time = 1 / (time_factor * 100)
old_interval = int(int(time.time()*time_factor) / interval_size)
current_timestamp = time.time()
current_interval = None

running = True
while running:
    current_timestamp = int(time.time() * time_factor)
    current_interval = int(t_s / interval_size)
    if (current_interval != old_interval):
        request_runtime = time.time()

        await self.do_time_sensitive_work()

        old_interval = current_interval
        request_runtime = time.time() - request_runtime
        await asyncio.sleep(1/(time_factor*100) - request_runtime )
    else:
        await asyncio.sleep(1/(time_factor*100))

推荐阅读