Django中的作业计划

时间:2018-07-19 16:06:02

标签: python django scheduled-tasks

我需要在我们的Django应用中实现计划任务。 DBader的schedule似乎很适合这份工作,但是当它作为Django项目的一部分运行时,似乎并没有产生预期的效果。

具体来说,这可以作为独立程序很好地工作:

import schedule
import time

import logging
log = logging.getLogger(__name__)

def handleAnnotationsWithoutRequests(settings):
    '''
    From settings passed in, grab job-ids list
    For each job-id in that list, perform annotation group/set logic [for details, refer to handleAnnotationsWithRequests(requests, username) 
                                                                     sans requests, those are obtained from db based on job-id ]
    '''
    print('Received settings: {}'.format(str(settings)))

def job():
    print("I'm working...")

#schedule.every(3).seconds.do(job)
#schedule.every(2).seconds.do(handleAnnotationsWithoutRequests, settings={'a': 'b'})
invoc_time = "10:33"
schedule.every().day.at(invoc_time).do(handleAnnotationsWithoutRequests, settings={'a': 'b'})

while True:
    schedule.run_pending()
    time.sleep(1)

但是在Django上下文中运行的(等效)代码不会导致调用。

def handleAnnotationsWithoutRequests(settings):
    '''
    From settings passed in, grab job-ids list
    For each job-id in that list, perform annotation group/set logic [for details, refer to handleAnnotationsWithRequests(requests, username) 
                                                                     sans requests, those are obtained from db based on job-id ]
    '''
    log.info('Received settings: {}'.format(str(settings)))

def doSchedule(settings):
    '''
    with scheduler library
    Based on time specified in settings, invoke .handleAnnotationsWithoutRequests(settings)
    '''
    #settings will need to be reconstituted from the DB first
    #settings = {}
    invocationTime = settings['running_at']
    import re
    invocationTime = re.sub(r'([AaPp][Mm])', "", invocationTime)
    log.info("Invocation time to be used: {}".format(invocationTime))
    schedule.every().day.at(invocationTime).do(handleAnnotationsWithoutRequests, settings=settings)

    while True:
        schedule.run_pending()
        time.sleep(1)

因此handleAnnotationsWithoutRequests()的日志不会出现在控制台上。

this scheduling library与Django兼容吗?有没有可以参考的使用示例?

我怀疑某些线程问题在这里起作用。也许还有更好的选择可以使用?欢迎提出建议。

谢谢。

2 个答案:

答案 0 :(得分:1)

我经常使用Django Commands

我使用的模式是在我的应用中设置一个新的Django命令,然后使其在永无休止的while()循环中成为一个长期运行的过程。

I循环使用自定义的sleep(1)计时器连续进行迭代。

这里是简短的版本,其中插入了一些伪代码。您可以在我的Django Reference Implementation中看到此模式的有效版本。

class Command(BaseCommand):
    help = 'My Long running job'

    def handle(self, *args, **options):

        self.stdout.write(self.style.SUCCESS(f'Starting long-running job.'))

        while True:

            if conditions met for job:
                self.job()

            sleep(5)

    def job(self):
        self.stdout.write(self.style.SUCCESS(f'Running the job...'))

答案 1 :(得分:0)

对于Web服务器,您可能不希望某些进程内运行:

  

An in-process scheduler for periodic jobs [...]

https://github.com/Tivix/django-cron被证明是可行的解决方案。

还有重量级冠军Celery和Celerybeat。