Задание не выполняется APScheduler BackgroundScheduler
У меня есть приложение Django, которое я запускаю на Docker. Я пытаюсь запустить планировщик APScheduler при запуске контейнера Docker.
Я создал планировщик и просто добавил к нему задание, которое я назвал test1, и оно отправляет электронное письмо на мой адрес.
Это скрипт Python, который запускается, когда я запускаю контейнер.
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.schedulers.background import BackgroundScheduler
#scheduler = BlockingScheduler()
scheduler = BackgroundScheduler()
def test1():
... (code to send email)
scheduler.add_job(test1, 'interval', seconds = 20)
scheduler.start()
Вот результаты, которые я получил с каждым из двух видов планировщиков:
- BlockingScheduler: планировщик работает, я получаю электронное письмо каждые 20 секунд. Однако я не могу получить доступ к приложению. Я предполагаю, что это нормально из-за самой природы BlockingScheduler.
- BackgroundScheduler: нет проблем с доступом к приложению. Тем не менее, я не получаю по электронной почте.
Поскольку электронные письма были отправлены в одном из двух случаев, я полагаю, что проблема не связана ни с Django, ни с Docker, а связана только с APScheduler. Я провел исследование, но не смог понять, почему BackgroundScheduler не работает, как в прочитанных мною учебниках, разработчик настроил планировщик так же, как и я.
Любая помощь будет высоко ценится, спасибо!
ОБНОВЛЕНИЕ 1
Я попробовал две следующие вещи, обе заставили BackgroundScheduler вести себя как BlockingScheduler (это не то, что я хочу)
1) Установка опции демона в False при инициализации экземпляра планировщика:
scheduler = BackgroundScheduler(daemon = False)
2) "Попытка поддержать основной поток", как объяснено в этих:
как-д-я-график-ан-интервальная работа-с apscheduler
apscheduler-внутри-а-класс-объект
Я добавил это сразу после scheduler.starts():
while True:
time.sleep(1)
scheduler.shutdown()
ОБНОВЛЕНИЕ 2
Когда я пытаюсь настроить BackgroundScheduler в одном файле Python (вне контекста приложения), он работает очень хорошо:
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.schedulers.blocking import BlockingScheduler
def test1():
print('issou')
scheduler = BackgroundScheduler()
scheduler.start()
scheduler.add_job(test1, 'interval', seconds=5)
print('yatangaki')
Сначала печатается "ятангаки", а затем "каждые пять секунд", так что все выглядит хорошо.
ОБНОВЛЕНИЕ 3
Теперь я попытался запустить планировщик в приложении Django, с которым я работал локально python manage.py runserver
, без использования Docker.
Он работает отлично: письма отправляются, и я могу получить доступ к основному виду приложения.
Примечание: BackgroundScheduler запускается функцией под названием start_test1
, В этом приложении я бегу start_test1
в файле верхнего уровня urls.py. В другом приложении, которое я запускаю с помощью Docker, которое я хочу использовать в конце концов, - start_test1
запускается в скрипте Python, который сам запускается в файле.sh, который я запускаю с помощью команды CMD Docker.
2 ответа
Похоже, это было все о том, где запустить планировщик и добавить работу.
В том, что я сделал изначально (поместив код в файл.sh), BackgroundScheduler запустился, но скрипт Python сразу же завершился после запуска, так как у него не было блокирующего поведения и sh. Файл на самом деле не был частью приложения (он используется Dockerfile, а не приложением).
В итоге я нашел решение здесь: execute-code-when-django-запуска-единожды. В моем приложении не было файла apps.py, поэтому я создал его и следовал инструкциям в этой теме.
Теперь работает нормально.
У меня похожая проблема, но она решилась только тем, что не блокировал воркер:
# working:
def worker():
phone_elm = ....
thread = threading.Thread(target=work, args=(phone_elm,))
thread.start()
# not working:
def worker():
phone_elm = ....
work(phone_elm)
scheduler2 = BackgroundScheduler(timezone="Asia/Kolkata")
# schedule scanning running of folder's running file
scheduler2.add_job(worker, 'interval', seconds=15, max_instances=5000)
scheduler1.start()
Я имею в виду, что не работает, это то, что после 10 ~ раз, когда он сработал, он был остановлен без причины, снова запущен после того, как 1 из 10 остановился (работа завершилась)
Это тоже часть Django, но понятно, что старт не завершается...