Вопрос-Ответ

How to repeatedly execute a function every x seconds?

Как повторно выполнять функцию каждые x секунд?

Я хочу многократно выполнять функцию в Python каждые 60 секунд вечно (точно так же, как NSTimer в Objective C или setTimeout в JS). Этот код будет выполняться как демон и фактически аналогичен вызову скрипта python каждую минуту с использованием cron, но не требует настройки пользователем.

В этом вопросе о cron, реализованном на Python, решение, похоже, эффективно просто sleep() в течение x секунд. Мне не нужна такая расширенная функциональность, поэтому, возможно, сработало бы что-то вроде этого

while True:
# Code executed here
time.sleep(60)

Есть ли какие-либо предсказуемые проблемы с этим кодом?

Переведено автоматически
Ответ 1

Если в вашей программе еще нет цикла обработки событий, используйте модуль sched, который реализует планировщик событий общего назначения.

import sched, time

def do_something(scheduler):
# schedule the next call first
scheduler.enter(60, 1, do_something, (scheduler,))
print("Doing stuff...")
# then do your stuff

my_scheduler = sched.scheduler(time.time, time.sleep)
my_scheduler.enter(60, 1, do_something, (my_scheduler,))
my_scheduler.run()

Если вы уже используете библиотеку циклов событий, такую как asyncio, trio, tkinter, PyQt5 gobject, kivy,,, и многие другие - просто запланируйте задачу, используя вместо этого методы вашей существующей библиотеки циклов событий.

Ответ 2

Привязать временной цикл к системным часам следующим образом:

import time
starttime = time.monotonic()
while True:
print("tick")
time.sleep(60.0 - ((time.monotonic() - starttime) % 60.0))

Используйте "монотонные" часы для правильной работы; time () регулируется изменениями солнечного / юридического времени, синхронизацией ntp и т.д...

Ответ 3

Если вам нужен неблокирующий способ периодического выполнения вашей функции, вместо блокирующего бесконечного цикла я бы использовал поточный таймер. Таким образом, ваш код может продолжать выполняться и выполнять другие задачи, при этом ваша функция по-прежнему вызывается каждые n секунд. Я часто использую этот метод для печати информации о ходе выполнения длительных задач с интенсивным использованием процессора / диска / сети.

Вот код, который я опубликовал в аналогичном вопросе, с элементами управления start() и stop():

from threading import Timer

class RepeatedTimer(object):
def __init__(self, interval, function, *args, **kwargs):
self._timer = None
self.interval = interval
self.function = function
self.args = args
self.kwargs = kwargs
self.is_running = False
self.start()

def _run(self):
self.is_running = False
self.start()
self.function(*self.args, **self.kwargs)

def start(self):
if not self.is_running:
self._timer = Timer(self.interval, self._run)
self._timer.start()
self.is_running = True

def stop(self):
self._timer.cancel()
self.is_running = False

Использование:

from time import sleep

def hello(name):
print "Hello %s!" % name

print "starting..."
rt = RepeatedTimer(1, hello, "World") # it auto-starts, no need of rt.start()
try:
sleep(5) # your long-running job goes here...
finally:
rt.stop() # better in a try/finally block to make sure the program ends!

Характеристики:


  • Только стандартная библиотека, никаких внешних зависимостей

  • start() и stop() безопасно вызывать несколько раз, даже если таймер уже запущен / остановлен

  • вызываемая функция может иметь позиционные и именованные аргументы

  • Вы можете изменить interval в любое время, это вступит в силу после следующего запуска. То же самое для args, kwargs и даже function!

Ответ 4

Возможно, вы захотите рассмотреть Twisted, сетевую библиотеку Python, которая реализует шаблон Reactor.

from twisted.internet import task, reactor

timeout = 60.0 # Sixty seconds

def doWork():
#do work here
pass

l = task.LoopingCall(doWork)
l.start(timeout) # call every sixty seconds

reactor.run()

Хотя "while True: sleep (60)", вероятно, будет работать, Twisted, вероятно, уже реализует многие функции, которые вам в конечном итоге понадобятся (демонизация, ведение журнала или обработка исключений, как указано bobince), и, вероятно, будет более надежным решением

python