python apscheduler_源码分析python apscheduler的实现

今天的话题是,源码分析python apscheduler计划任务的实现.  不知道为什么总是跟计划任务较真,自己一些实现了一个分布式的定时任务系统,也在博客中做过分享,但还是很喜欢看看别人是怎么写的,有什么可以借鉴的。

新版的apscheduler 3.1.x有些太杂乱了,在3.x版本里面加了各种的运行模式,比如gevent,多进程啥的. 如果只是想看他的实现原理那我们就直接看他的经典版本2.1版本。

那可能有人问了,你丫怎么知道apscheduler的经典版是2.x? 我用apscheduler真的是很久以前了. 曾经用apschedule加tornado开发对内的计划任务系统。

我们首先把apscheduler的代码切到2.1的commit.

git clone https://bitbucket.org/agronholm/apscheduler.git

cd apscheduler

git checkout 3a4a0a4

下面是apscheduler的2.1版本的测试代码,看起来很是简单。他的执行效果也会是字面理解的那种,每隔一段时间去执行tick和h5函数,不会出现堵塞情况.

#blog: xiaorui.cc

import sys

import time

from datetime import datetime

from apscheduler.scheduler import Scheduler

def tick():

sys.stdout.write('Tick! The time is: %s\n' % datetime.now())

def h5():

time.sleep(5)

sys.stdout.write("this is h5 func")

if __name__ == '__main__':

scheduler = Scheduler()

scheduler.add_interval_job(tick, seconds=2)

scheduler.add_interval_job(h5, seconds=1)

sys.stdout.write('Press Ctrl+C to exit\n')

scheduler.start()

废话少说,现在开始按调度步骤来分析下apscheduler的源代码. apscheduler的代码没有用到python中的黑魔法,实现的方案也比较的中规中矩。

主要就利用了python threading Event 和 Lock锁。

scheduler = Scheduler()

首先我们需要实例化Scheduler类,这个类初始化了必要的一些结构.

scheduler.add_interval_job(tick, seconds=2)

添加一条任务,apscheduler首先会把这条任务用Job来包装下。

job = Job(trigger, func, args or [], kwargs or {},

options.pop('misfire_grace_time', self.misfire_grace_time),

options.pop('coalesce', self.coalesce), **options)

if not self.running:

self._pending_jobs.append((job, jobstore))

else:

self._real_add_job(job, jobstore, True)

return job

Apscheduler定时任务有三种,一种是add_date_job,传递是datetime类型的时间对象。  add_interval_job是循环执行, 可以秒,分,时,天,星期.  add_cron_job跟前面的add_interval_job有些像,但他的场景是单次.

总的来说把一堆的任务加入到 self._pending_jobs, self._jobstores, self._listeners之后,开始正经干活.

def start(self):

for job, jobstore in self._pending_jobs:

self._real_add_job(job, jobstore, False)

del self._pending_jobs[:]

self._stopped = False

self._thread = Thread(target=self._main_loop, name='APScheduler')

self._thread.setDaemon(self.daemonic)

self._thread.start()

def _main_loop(self):

self._wakeup.clear()

while not self._stopped:

logger.debug('Looking for jobs to run')

now = datetime.now()

next_wakeup_time = self._process_jobs(now)

if next_wakeup_time is not None:

wait_seconds = time_difference(next_wakeup_time, now)

logger.debug('Next wakeup is due at %s (in %f seconds)',

next_wakeup_time, wait_seconds)

#会一直wait等待.

self._wakeup.wait(wait_seconds)

else:

logger.debug('No jobs; waiting until a job is added')

self._wakeup.wait()

self._wakeup.clear()

logger.info('Scheduler has been shut down')

这个函数主要是用来判断任务是否到了执行的时间. 需要主要的是,在实例化Scheduler类的时候会创建一组默认线程数为20的线程池。这个线程池用来执行真正的任务。

如下面的意思是,时间一到就立马提交给submit去调度任务.

#blog: xiaorui.cc

if run_times:

self._threadpool.submit(self._run_job, job, run_times)

def _process_jobs(self, now):

next_wakeup_time = None

self._jobstores_lock.acquire()

try:

for alias, jobstore in iteritems(self._jobstores):

for job in tuple(jobstore.jobs):

run_times = job.get_run_times(now)

if run_times:

self._threadpool.submit(self._run_job, job, run_times)

Apscheduler的代码解析就说到这边了,其实代码本身很是简练,值得大家好好琢磨下.

大家觉得文章对你有些作用!

如果想赏钱,可以用微信扫描下面的二维码,感谢!

另外再次标注博客原地址  xiaorui.cc

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值