Как мне запланировать интервальную работу с 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? Пока что это единственная известная операционная система, в которой автоматическое определение местного часового пояса невозможно.

Другие вопросы по тегам