Рассмотрим код ниже: def set_ntp_time (): times = [] для адреса в ntp_addresses: ntp_client = ntplib.NTPClient () ntp_response = ntp_client.request (address, version = 3) ...

0
Ali Bahaari 4 Янв 2021 в 23:07

1 ответ

Лучший ответ

ИМХО, подход прост:

  1. Получите время NTP (я назову его now)
  2. Определите время, в которое вы хотите запустить код (runat)
  3. Рассчитайте разницу
  4. Спи на это время
  5. Делай все, что хочешь в то время

Обратите внимание, что запрос времени у серверов NTP сам по себе займет некоторое время. Поэтому, если вы напечатаете время NTP как часть шага 5, оно всегда будет отображаться поздно. Я буду использовать местное время, чтобы компенсировать это в приведенном ниже коде.

from time import sleep
import ntplib
from datetime import datetime


def get_ntp_time() -> datetime:
    ntp_pool = ['0.pool.ntp.org', 'uk.pool.ntp.org', 'ie.pool.ntp.org']
    for item in ntp_pool:
        call = ntplib.NTPClient()
        response = call.request(item, version=3)
        try:
            t = datetime.fromtimestamp(response.orig_time)
            return t  # Use the time of the first NTP server that returns a time
        except:  # no response from server
            pass


now = get_ntp_time()
runat = datetime(now.year, now.month, now.day, now.hour, now.minute + 1, 0)  # Arbitrary, put 8:30 here
print("NTP time:", now)
print("Time to wait:", runat - now)
sleep((runat - now).total_seconds())

localbefore = datetime.now()
print("Running the job ...")
now = get_ntp_time()
localafter = datetime.now()
print("NTP time:", now)
print("Job ran at: ", now - (localafter - localbefore))

Пример вывода:

NTP time: 2021-01-05 15:43:21.772182
Time to wait: 0:00:38.227818
Running the job ...
NTP time: 2021-01-05 15:44:00.031360
Job ran at:  2021-01-05 15:44:00.010784

Вероятно, вы не приблизитесь намного ближе, чем 17 мс, поскольку планирование потоков в Windows происходит с 1/64 секунды.

time = min(times)

Это не сработает. Минимальное время слишком давно. Если вы спросите у всех серверов время в цикле, время пройдет. Если вы спросите все три сервера, вам нужно взять максимальное время.

1
Thomas Weller 5 Янв 2021 в 14:53