Как запланировать интервальное задание с помощью 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 для промежуточной подготовки). У меня есть другие задания apscheduler cron, которые отлично работают в промежуточных/производственных средах.

Когда я включаю ведение журнала DEBUG для регистратора «apscheduler.schedulers», в журнале указывается, что добавлено задание интервала:

Добавлено задание "my_cron_job1" в хранилище заданий "по умолчанию"
Добавлено задание "my_cron_job2" в хранилище заданий "по умолчанию"
Добавлено задание "my_interval_job" в хранилище заданий "по умолчанию"
Планировщик запущено
Предварительное добавление задания – оно будет правильно запланировано при запуске планировщика
Предварительное добавление задания – оно будет правильно запланировано при запуске планировщика
Поиск заданий для запуска
Ожидается следующее пробуждение в 2015-03-24 15:05:00-07:00 (через 254,210542 секунды)

Как следующее пробуждение может произойти через 254 секунды, если интервал задания установлен на 5 секунд??


person Troy    schedule 24.03.2015    source источник


Ответы (5)


Вам нужно сохранить ветку живой. Вот пример того, как я его использовал.

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()
person Riaan Steyn    schedule 30.11.2017

Я не понял, что вызвало первоначальную проблему, но я обошел ее, поменяв порядок, в котором запланированы задания, так что задание «интервал» запланировано ДО заданий «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 и интервальные задания выполняются без проблем в обеих средах.

person Troy    schedule 24.03.2015
comment
Я бы рекомендовал не указывать такой часовой пояс. Я только что помог решить проблему перехода на летнее время, когда разработчик указал часовой пояс EST. Переключение на Америку/Нью-Йорк вместо этого решило проблему. Всегда отдавайте предпочтение названиям часовых поясов, основанным на локали, потому что они никогда не бывают двусмысленными. - person Alex Grönholm; 26.03.2015

Как следующее пробуждение может произойти через 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

Чтобы узнать больше, ознакомьтесь с документацией здесь.

person Amirkhm    schedule 19.12.2018

В документации была ошибка. Я исправил это сейчас. Эта первая строка должна быть:

from apscheduler.schedulers.blocking import BlockingScheduler

Однако это вызвало бы ошибку ImportError, но вы ничего не упомянули. Пробовали ли вы какие-либо из предоставленных примеров?

person Alex Grönholm    schedule 24.03.2015
comment
У меня действительно было from apscheduler.schedulers.blocking import BlockingScheduler в моем коде. Я просто неправильно скопировал строку в вопрос о стеке. Я исправил свой первоначальный вопрос и добавил некоторые другие обновления. - person Troy; 25.03.2015

Хорошо, я посмотрел обновленный вопрос.

Причина, по которой у вас возникли проблемы, может заключаться в том, что вы используете неправильный часовой пояс. В настоящее время в вашей стране в большинстве мест используется переход на летнее время, поэтому правильным часовым поясом, вероятно, будет MDT (горное летнее время). Но это снова сломается, когда вы вернетесь к стандартному времени. Поэтому я советую вам использовать часовой пояс, например «Америка/Денвер». Это позаботится о переключателях DST.

Вопрос: Вы используете CentOS? Пока что это единственная известная операционная система, в которой невозможно автоматическое определение местного часового пояса.

person Alex Grönholm    schedule 26.03.2015