Я хочу постоянно выполнять функцию в Python каждые 60 секунд навсегда (точно так же, как NSTimer в Objective C). Этот код будет работать как демон и по сути похож на вызов сценария python каждую минуту с использованием cron, но без необходимости его установки пользователем.
В этом вопросе о cron, реализованном в Python , решение, по-видимому, эффективно просто sleep () на x секунд. Мне не нужны такие расширенные функциональные возможности, так что, возможно, что-то подобное будет работать
while True:
# Code executed here
time.sleep(60)
Есть ли предсказуемые проблемы с этим кодом?
time.sleep(60)
может вернуться как раньше, так и позжеОтветы:
Если ваша программа еще не имеет цикла обработки событий, используйте модуль sched , который реализует планировщик событий общего назначения.
Если вы уже используете библиотеку цикла события , как
asyncio
,trio
,tkinter
,PyQt5
,gobject
,kivy
, и многие другие - просто запланировать задачу с помощью методов существующей библиотеки цикла обработки событий, вместо.источник
enterabs()
чтобы избежать этого. Вот не дрейфующая версия для сравнения .time.sleep
здесь могут накапливаться ошибки . «Выполнять каждые X секунд» и «Выполнять с задержкой ~ X секунд повторно» - это не одно и то же. Смотрите также этот комментарийЗаблокируйте ваш цикл времени на системные часы, как это:
источник
twisted
ответ - единственные ответы, которые запускают функцию каждуюx
секунду. Остальные выполняют функцию с задержкой вx
секунды после каждого звонка.from time import time, sleep
из-за экзистенциальных последствий;)starttime
если вы начнете синхронизировать его с определенным временем:time.sleep(60 - time.time() % 60)
у меня все работает нормально. Я использовал его какtime.sleep(1200 - time.time() % 1200)
и он дает мне логи:00 :20 :40
, так, как я хотел.sleep()
,timer()
точности и сколько времени требуется , чтобы выполнить тело цикла , но в среднем итераций всегда происходят на границах интервалов (даже если некоторые из них пропущены):while keep_doing_it(): sleep(interval - timer() % interval)
. Сравните это с тем,while keep_doing_it(): sleep(interval)
где ошибки могут накапливаться после нескольких итераций.Возможно, вы захотите рассмотреть Twisted - сетевую библиотеку Python, которая реализует шаблон Reactor .
Хотя «while True: sleep (60)», вероятно, будет работать, Twisted, вероятно, уже реализует многие функции, которые вам в конечном итоге понадобятся (демонизация, ведение журнала или обработка исключений, как указано в bobince), и, вероятно, будет более надежным решением.
источник
Если вы хотите, чтобы неблокирующий способ выполнял вашу функцию периодически, вместо блокирующего бесконечного цикла, я бы использовал потоковый таймер. Таким образом, ваш код может продолжать работать и выполнять другие задачи, при этом ваша функция вызывается каждые n секунд. Я часто использую эту технику для распечатки информации о проделанной работе в длинных, ресурсоемких / сетевых задачах.
Вот код, который я разместил в похожем вопросе с элементами управления start () и stop ():
Использование:
Особенности:
start()
иstop()
безопасно звонить несколько раз, даже если таймер уже запущен / остановленinterval
любое время, это будет эффективно после следующего запуска. То же самоеargs
,kwargs
и дажеfunction
!источник
def _run(self)
Я пытаюсь обернуть вокруг моей головы , почему вы называетеself.start()
до тогоself.function()
. Можете ли вы уточнить? Я бы подумал, что звонитьstart()
первымself.is_running
всегда будетFalse
так, тогда мы всегда будем раскручивать новый поток.x
секунду (т. Е. T = 0, t = 1x, t = 2x, t = 3x, ...), где в исходном коде образца постеров выполняется функция с интервалом x секунд между ними. Кроме того, это решение, на мой взгляд, содержит ошибку, еслиinterval
оно короче времени, которое требуетсяfunction
для выполнения. В этом случаеself._timer
будет перезаписано вstart
функции..function()
after.start()
должен запускать функцию при t = 0. И я не думаю, что это будет проблемой, еслиfunction
займет больше времениinterval
, но да, в коде могут быть некоторые гоночные условия.Более простой способ, которым я верю:
Таким образом, ваш код выполняется, затем он ждет 60 секунд, затем он выполняется снова, ждет, выполняет и т. Д ... Не нужно усложнять вещи: D
источник
time.sleep()
запуск чего-либо каждые X секундtime.sleep()
вwhile True
цикле, как:def executeSomething(): print('10 sec left') ; while True: executeSomething(); time.sleep(10)
Если вы хотите сделать это без блокировки оставшегося кода, вы можете использовать его, чтобы запустить в своем собственном потоке:
Это решение сочетает в себе несколько функций, редко встречающихся в других решениях:
threading.Timer
или чем-то еще), это приведет к прекращению цепочки. Тогда дальнейших казней не будет, даже если причина проблемы уже устранена. Простой цикл и ожидание с простымsleep()
гораздо более надежным по сравнению.next_time += delay
вместо этого.источник
Вот обновление кода от MestreLion, которое позволяет избежать дрейфа с течением времени.
Класс RepeatedTimer здесь вызывает данную функцию каждые «интервальные» секунды в соответствии с запросом OP; расписание не зависит от того, сколько времени займет выполнение функции. Мне нравится это решение, так как оно не имеет внешних библиотечных зависимостей; это просто чистый питон.
Пример использования (скопировано из ответа MestreLion):
источник
Я столкнулся с подобной проблемой некоторое время назад. Может быть http://cronus.readthedocs.org может помочь?
Для v0.2 работает следующий фрагмент
источник
Основное различие между этим и cron заключается в том, что исключение убьет демона навсегда. Возможно, вы захотите заключить в ловушку исключений и регистратор.
источник
Один из возможных ответов:
источник
Я закончил тем, что использовал модуль расписания . API это хорошо.
источник
Я использую метод Tkinter after (), который не «крадет игру» (как модуль sched, который был представлен ранее), т.е. он позволяет другим вещам работать параллельно:
do_something1()
иdo_something2()
может работать параллельно и с любым интервалом скорости. Здесь второй будет выполнен вдвое быстрее. Обратите внимание, что я использовал простой счетчик в качестве условия для завершения любой функции. Вы можете использовать любое другое условие, которое вам нравится, или нет, если вы хотите выполнить функцию до завершения программы (например, часы).источник
after
не позволяет вещам работать параллельно. Tkinter является однопоточным и может делать только одно за раз. Если что-то запланированноеafter
выполняется, оно не работает параллельно с остальным кодом. Если обаdo_something1
иdo_something2
запланированы для запуска в то же время, они будут работать последовательно, а не параллельно.sched
решении, и оно будет работать точно так же, как у вас.Вот адаптированная версия к коду от MestreLion. В дополнение к исходной функции этот код:
1) добавить first_interval, используемый для запуска таймера в определенное время (вызывающему необходимо вычислить first_interval и передать)
2) решить условие гонки в оригинальном коде. В исходном коде, если потоку управления не удалось отменить запущенный таймер («Остановите таймер и отмените выполнение действия таймера. Это будет работать только в том случае, если таймер все еще находится в стадии ожидания». Цитируется из https: // docs.python.org/2/library/threading.html ), таймер будет работать бесконечно.
источник
Это кажется намного проще, чем принятое решение - есть ли у него недостатки, которые я не рассматриваю? Пришел сюда в поисках какой-то простой пасты и был разочарован.
Который асинхронно выводит.
Это имеет дрейф в том смысле, что если выполняемая задача занимает заметное количество времени, то интервал становится равным 2 секундам + время задачи, поэтому, если вам нужно точное планирование, то это не для вас.
Обратите внимание на
daemon=True
флаг означает, что этот поток не будет блокировать закрытие приложения. Например, имелась проблема сpytest
зависанием на неопределенный срок после запуска тестов в ожидании прекращения этой игры.источник
Я использую это, чтобы вызвать 60 событий в час с большинством событий, происходящих в то же самое количество секунд после целой минуты:
В зависимости от реальных условий вы можете получить отметки длины:
но через 60 минут у вас будет 60 тиков; и большинство из них будет происходить с правильным смещением до минуты, которую вы предпочитаете.
В моей системе я получаю типичный дрейф <1/20 секунды, пока не возникнет необходимость в коррекции.
Преимущество этого метода - разрешение смещения часов; что может вызвать проблемы, если вы делаете такие вещи, как добавление одного элемента за тик и ожидаете 60 добавленных элементов в час. Невозможность учесть дрейф может привести к тому, что вторичные признаки, такие как скользящие средние, будут учитывать данные слишком глубоко в прошлом, что приведет к ошибочному выводу.
источник
например, Показать текущее местное время
источник
источник
Вот еще одно решение без использования дополнительных библиотек.
источник