【问题标题】:Assistance with running a few lines of code at an EXACT time帮助在准确的时间运行几行代码
【发布时间】:2021-02-22 03:38:04
【问题描述】:

我是学习 python 的新手,过去 2 天我一直在寻找这个问题的答案。我想添加可以使它暂停脚本(而不是结束它)的代码,然后在准确的时间运行它下面的几行。例如,如果我想让它暂停到晚上 10:40,我需要它精确到毫秒。示例:2021 2 21 22 40 00 00 年月日时分秒秒毫秒

我得到的最接近它的代码并没有准确地完成,而且大部分时间都有一秒或更长时间的延迟。

t = time_module.strptime('2021-02-21 22:25:14', '%Y-%m-%d %H:%M:%S')
t = time_module.mktime(t)
scheduler_e = scheduler.enterabs(t, 1, myfunc, ())
scheduler.run()

【问题讨论】:

标签: python


【解决方案1】:

您可以使用time 模块来执行此操作:

import time

def call_at_time(fun, t):
    sleep_time = t - time.time()
    assert sleep_time > 0  # make sure t is in the future
    time.sleep(sleep_time)
    fun()

使用这个函数看起来像这样:

t = time.strptime("2021-02-22 23:50:30", "%Y-%m-%d %H:%M:%S")
t = time.mktime(t)
print(f"scheduled at {t}")
call_at_time(lambda: print(f"hello at {time.time()}"), t)

那么这有多准确?这是一个小实验来找出答案。如果您想要更可靠的结果,请使用更大的n

n = 20
results = []
for _ in range(n):
    t = time.time() + 2  # 2 seconds in the future
    call_at_time(lambda: results.append(abs(time.time() - t)), t)
print(f"min={min(results):5.4f}, max={max(results):5.4f}, mean={sum(results) / n:5.4f}")

在我的 Windows 机器上,这给了我:

min=0.0010, max=0.0200, mean=0.0094

因此,我们平均减少了大约 9 毫秒,但有时我们减少了多达 20 毫秒。这种不准确来自两个来源

  1. time.sleep 并没有给你完美的保证(它可能会睡得更短或更长)
  2. time.time() 不一定具有很高的准确性,具体取决于您的系统。例如,请参阅讨论 here

为了说明 time.time() 的(不)准确性,您可以在循环中运行它并打印结果数字。

while True:
    print(time.time())

在我的 Windows 机器上,这给了我这样的东西:

...
1614072496.454525
1614072496.454525
1614072496.454525
1614072496.4555244
1614072496.4555244
1614072496.4595287
1614072496.4595287
1614072496.4595287
1614072496.4595287
1614072496.4595287
1614072496.4595287
1614072496.4595287
1614072496.4605293
1614072496.4605293
1614072496.4605293
...

如您所见,time.time() 可能非常不稳定,这当然会限制您完成所需任务的准确度(以及我上面的实验结果实际上有多准确......)。


如果您使用的系统 time.time() 可以为您提供更好的准确性,或者您找到了另一种获得更好系统时间的方法,则可以通过将睡眠与一些忙碌的等待结合起来获得更好的结果。这样你至少可以消除你从 time.sleep() 得到的不准确性。

def call_at_time_high_precision(fun, t, busy_waiting_time=1):
    sleep_time = t - time.time()
    assert sleep_time > 0  # make sure time is in the future
    if sleep_time > busy_waiting_time:
        time.sleep(sleep_time - busy_waiting_time)
    while t > time.time():  # busy wait until the event
        pass
    fun()

【讨论】:

    猜你喜欢
    • 2018-04-17
    • 1970-01-01
    • 2011-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-16
    • 2023-01-09
    • 2021-02-03
    相关资源
    最近更新 更多