Я попытался использовать библиотеку apscheduler , так как в ней, похоже, реализовано выражение cron, однако я обнаружил 2 недостатка этого подхода. Одна из них заключается в том, что библиотека довольно странно интегрируется с асинхронным кодом, и это вина моей реализации. Вторая проблема заключается в том, что для запуска запланированной задачи требуется несколько миллисекунд, это небольшая проблема, однако планирование вручную позволяет избежать этой задержки, и я хочу, чтобы измерения были как можно ближе к «точному времени»
Я также пытался использовать сельдерея , однако это кажется большим излишним, необходимость установить 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))