APScheduler的BackgroundScheduler不执行作业

时间:2018-08-01 15:07:21

标签: python django docker apscheduler

我有一个在Docker上运行的Django应用程序。运行docker容器时,我正在尝试启动APScheduler调度程序。

我创建了一个调度程序,然后简单地将它添加到一个名为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的本质,我认为这是正常现象。

screenshot1

screenshot2

  • BackgroundScheduler:访问应用程序没有问题。但是,我没有收到电子邮件。

由于电子邮件是在两种情况之一中发送的,所以我认为问题与Django和Docker无关,而仅与APScheduler有关。我做了研究,但是找不到为什么BackgroundScheduler无法像我阅读的教程那样工作,开发人员以与我相同的方式设置了调度程序。

任何帮助将不胜感激,谢谢!

更新1

我尝试了以下两项操作,都使BackgroundScheduler的行为类似于BlockingScheduler(这不是我想要的)

1)初始化调度程序实例时,将守护程序选项设置为False:

scheduler = BackgroundScheduler(daemon = False)

2)“尝试使主线程保持活动状态”,如以下内容所述:

how-do-i-schedule-an-interval-job-with-apscheduler

apscheduler-inside-a-class-object

我在scheduler.starts()之后添加了此代码:

while True:
    time.sleep(1)
scheduler.shutdown()

更新2

当我尝试在单个Python文件中(在任何应用程序上下文之外)设置BackgroundScheduler时,效果很好:

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')

首先打印“ yatangaki”,然后每5秒钟打印一次“ issou”,所以一切似乎都很好。

更新3

现在,我尝试在不使用Docker的情况下,使用python manage.py runserver在本地运行的Django应用上启动调度程序。

它运行良好:发送电子邮件,我可以访问应用程序的主视图。

注意:BackgroundScheduler由称为start_test1的函数启动。在此应用程序中,我在顶级urls.py文件中运行start_test1。在另一个应用程序上(我要在Docker上运行的那个应用程序,这是我最终要使用的应用程序),start_test1是在Python脚本中启动的,而该脚本本身是在我运行的.sh文件中触发的通过CMD Docker命令。

1 个答案:

答案 0 :(得分:0)

看来,这一切都是在何处启动调度程序和添加作业的。

在我最初的工作中(将代码放入.sh文件中),BackgroundScheduler启动了,但是 Python脚本在运行后立即结束,因为它没有阻塞行为,并且sh。文件不是真正属于应用程序的一部分(它由Dockerfile使用,而不是由应用程序使用)。

我最终在这里找到解决方案: execute-code-when-django-starts-once-only 我的应用程序内部没有apps.py文件,因此我创建了一个文件并按照该线程中的说明进行操作。

现在工作正常。