Как мне запланировать интервальную работу с APScheduler?
Я пытаюсь запланировать интервальную работу с APScheduler (v3.0.0).
Я пробовал:
from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler()
def my_interval_job():
print 'Hello World!'
sched.add_job(my_interval_job, 'interval', seconds=5)
sched.start()
а также
from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler()
@sched.scheduled_job('interval', id='my_job_id', seconds=5)
def my_interval_job():
print 'Hello World!'
sched.start()
Либо должен работать в соответствии с документами, но работа никогда не срабатывает...
ОБНОВИТЬ:
Оказывается, что-то еще, связанное со средой, мешало выполнению задачи. Сегодня утром задача работает нормально, без каких-либо изменений в коде со вчерашнего дня.
ОБНОВЛЕНИЕ 2:
После дальнейшего тестирования я обнаружил, что "интервальные" задания кажутся в целом ненадежными... Приведенный выше код теперь работает в моей среде разработки, но не при развертывании в промежуточной среде (я использую приложение heroku для постановки). У меня есть другие задания cron'а для apscheduler, которые отлично работают в среде постановки / производства.
Когда я включаю ведение журнала DEBUG для регистратора "apscheduler.schedulers", журнал указывает, что добавляется интервальное задание:
Добавлено задание "my_cron_job1" в хранилище заданий "default"
Добавлено задание "my_cron_job2" в хранилище заданий "default"
Добавлено задание "my_interval_job" в хранилище заданий "default"
Планировщик запущен
Предварительное добавление задания - оно будет правильно запланировано при запуске планировщика
Предварительное добавление задания - оно будет правильно запланировано при запуске планировщика
Ищу работу для запуска
Следующее пробуждение должно произойти в 2015-03-24 15: 05: 00-07: 00 (через 254,210542 секунды)
Как может произойти следующее пробуждение через 254 секунды, если для интервала задано 5 секунд?
4 ответа
Вы должны поддерживать поток в живых. Вот пример того, как я это использовал.
from subprocess import call
import time
import os
from apscheduler.schedulers.background import BackgroundScheduler
def job():
print("In job")
call(['python', 'scheduler/main.py'])
if __name__ == '__main__':
scheduler = BackgroundScheduler()
scheduler.configure(timezone=utc)
scheduler.add_job(job, 'interval', seconds=10)
scheduler.add
scheduler.start()
print('Press Ctrl+{0} to exit'.format('Break' if os.name == 'nt' else 'C'))
try:
# This is here to simulate application activity (which keeps the main thread alive).
while True:
time.sleep(5)
except (KeyboardInterrupt, SystemExit):
# Not strictly necessary if daemonic mode is enabled but should be done if possible
scheduler.shutdown()
Я не понял, что вызвало первоначальную проблему, но я обошел ее, поменяв порядок, в котором запланированы задания, так что задание "интервала" запланировано ПЕРЕД заданиями "cron".
т.е. я перешел с этого:
def my_cron_job1():
print "cron job 1"
def my_cron_job2():
print "cron job 2"
def my_interval_job():
print "interval job"
if __name__ == '__main__':
from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler(timezone='MST')
sched.add_job(my_cron_job1, 'cron', id='my_cron_job1', minute=10)
sched.add_job(my_cron_job2, 'cron', id='my_cron_job2', minute=20)
sched.add_job(my_interval_job, 'interval', id='my_job_id', seconds=5)
к этому:
def my_cron_job1():
print "cron job 1"
def my_cron_job2():
print "cron job 2"
def my_interval_job():
print "interval job"
if __name__ == '__main__':
from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler(timezone='MST')
sched.add_job(my_interval_job, 'interval', id='my_job_id', seconds=5)
sched.add_job(my_cron_job1, 'cron', id='my_cron_job1', minute=10)
sched.add_job(my_cron_job2, 'cron', id='my_cron_job2', minute=20)
и теперь и задания cron, и задания интервала выполняются без проблем в обеих средах.
Как может произойти следующее пробуждение через 254 секунды, если для интервала задано 5 секунд?
Это просто: у вас есть много ожидающих выполнения, так как большинство ваших заданий не было выполнено в интервале времени.
Вы можете использовать следующие параметры, чтобы разобраться в этом:
**misfire_grace_time**: Maximum time in seconds for the job execution to be allowed to delay before it is considered a misfire
**coalesce**: Roll several pending executions of jobs into one
Чтобы узнать больше, ознакомьтесь с документацией здесь.
В документации там была ошибка. Я исправил это сейчас. Эта первая строка должна быть:
from apscheduler.schedulers.blocking import BlockingScheduler
Хотя это вызвало бы ошибку ImportError, но вы ничего не упомянули. Вы пробовали какой-либо из приведенных примеров?
Хорошо, я посмотрел на обновленный вопрос.
Причиной возникновения проблем может быть то, что вы используете неправильный часовой пояс. Ваша страна в настоящее время использует летнее время в большинстве мест, поэтому правильным часовым поясом, вероятно, будет MDT (горное летнее время). Но это снова сломается, когда вы вернетесь к стандартному времени. Поэтому я советую вам использовать часовой пояс, такой как "Америка / Денвер". Это позаботится о переключателях DST.
Вопрос: Вы используете CentOS? Пока что это единственная известная операционная система, в которой автоматическое определение местного часового пояса невозможно.