Вопрос:
Я хочу иметь возможность запускать функцию каждую секунду, не относящуюся к длительности функции (она всегда должна быть ниже секунды). Я рассмотрел несколько вариантов, но не уверен, что лучше.
Если я просто использую функцию задержки, он не будет учитывать время, которое функция выполняет для выполнения.
Если я заработаю функцию, а затем вычитаю ее из второй и составляю остаток в задержке, она не будет учитывать расчеты времени.
Я пробовал использовать threading.timer(я не уверен в том, что это работает), но он казался медленнее, чем 1s.
Вот код, который я пробовал для тестирования threading.timer:
def update(i): sys.stdout.write(str(i)+’r’) sys.stdout.flush() print i i += 1 threading.Timer(1, update, [i]).start()
Есть ли способ сделать это не относящимся к длительности времени, которое занимает функция?
Лучший ответ:
Это сделает это, и его точность не будет дрейфовать со временем.
import time start_time = time.time() interval = 1 for i in range(20): time.sleep(start_time + i*interval — time.time()) f() Ответ №1
Просто поставьте синхронизированный вызов в начале вашей функции, чтобы получить правильный интервал:
def update(i): threading.Timer(1, update, [i]).start() sys.stdout.write(str(i)+’r’) sys.stdout.flush() print i i += 1
Как видно здесь.
Ответ №2
Как насчет этого: после каждого прогона засыпайте (1.0 — launch interval) секунды. Вы можете изменить условие завершения, изменив while True:. Хотя, если ваша функция занимает более 1 секунды для запуска, это пойдет не так.
from time import time, sleep while True: startTime = time() yourFunction() endTime = time()-startTime sleep(1.0-endTime) Ответ №3
Threading может быть хорошим выбором. Основная концепция заключается в следующем.
import threading def looper(): # i as interval in seconds threading.Timer(i, looper).start() # put your action here foo() #to start looper() Ответ №4
если f() всегда занимает меньше секунды, а затем запускает его на одной второй границе (без дрейфа):
import time while True: time.sleep(1 — time.monotonic() % 1)) f()
Идея от @Dave Rove отвечает на аналогичный вопрос.
Чтобы понять, как это работает, рассмотрите пример:
- time.monotonic() возвращает 13.7 и time.sleep(0.3) называется
- f() вызывается вокруг (± некоторая ошибка) 14 секунд (с time.monotonic() эпохи)
- f() запускается и занимает 0.1 (< 1) секунд
- time.monotonic() возвращает < <2 → второй и time.sleep(0.9) называется
- шаг 2. повторяется около 15 секунд, так как time.monotonic() epoch
- f() выполняется и занимает 0.3 (< 1) секунд (примечание: значение отличается от шага 2).
- time.monotonic() возвращает 15.3 и time.sleep(0.7) называется
- f() вызывается вокруг 16 секунд, и цикл повторяется.
На каждом шаге f() вызывается на одной второй границе (согласно таймеру time.monotonic()). Ошибки не накапливаются. Нет дрейфа.
Смотрите также: Как периодически запускать функцию в python (используя tkinter).