Есть ли что-то в Python 2.7, сродни Go `time.Tick` или Netty`HashedWheelTimer`?
Я пишу много кода, который опирается на точные периодические вызовы методов. Я использовал Python futures
библиотека для отправки вызовов в пул потоков среды выполнения и ожидания между вызовами в цикле:
executor = ThreadPoolExecutor(max_workers=cpu_count())
def remote_call():
# make a synchronous bunch of HTTP requests
def loop():
while True:
# do work here
executor.submit(remote_call)
time.sleep(60*5)
Тем не менее, я заметил, что эта реализация вносит некоторый дрейф после долгой работы (например, я запускал этот код в течение 10 часов и заметил около 7 секунд дрейфа). Для моей работы мне нужно, чтобы он работал с точностью до секунды, а миллисекунда была бы еще лучше. Некоторые люди указали мне на asyncio
( "Запусти и забудь" python async / await), но я не смог заставить это работать в Python 2.7.
Я не ищу взломать. Что я действительно хочу, так это что-то похожее на Go time.Tick
или нетти HashedWheelTimer
,
1 ответ
Ничего подобного не приходит с Python. Вам необходимо вручную настроить время сна, чтобы учесть время, потраченное на работу.
Вы можете сложить это в итератор, так же, как канал Го time.Tick
:
import itertools
import time
import timeit
def tick(interval, initial_wait=False):
# time.perf_counter would probably be more appropriate on Python 3
start = timeit.default_timer()
if not initial_wait:
# yield immediately instead of sleeping
yield
for i in itertools.count(1):
time.sleep(start + i*interval - timeit.default_timer())
yield
for _ in tick(300):
# Will execute every 5 minutes, accounting for time spent in the loop body.
do_stuff()
Обратите внимание, что тикер выше начинает тикать при запуске итерации, а не при вызове tick
, что имеет значение, если вы попытаетесь запустить тикер и сохранить его на потом. Кроме того, он не отправляет время и не сбрасывает тики, если приемник работает медленно. Вы можете настроить все это самостоятельно, если хотите.