首页 > 编程语言 >django-crontab项目源码阅读

django-crontab项目源码阅读

时间:2024-03-14 09:59:38浏览次数:19  
标签:... jobs self crontab django job 源码

文章同步首发个人公众号 菩提老鹰 ,欢迎大家订阅

一、知识点

这边源码阅读分析,可以获得如下知识点

1、django-crontab的原理

2、django-crontab任务ID如何生产

3、django-crontab使用限制


很早之前写过关于django-crontab的文章,比如

django 任务管理之crontab

Django实现crontab远程任务管理系统

今天在和一个朋友聊运维平台任务管理中心的问题时,突然想起来django-crontab在进行任务的管理时:

1、先在Django项目中开发相关的功能函数

2、然后在 项目settings.py 中配置 CRONJOBS 列表变量

3、最后通过 python manage.py crontab add 添加任务


这里有几个问题思考

二、crontab add的时候,遇到的问题

其实是先删除所有的旧的,然后再创建所有的任务

源码参考

# django_crontab/management/commands/crontab.py
def handle(self, *args, **options):
    """
    Dispatches by given subcommand
    """
    if options['subcommand'] == 'add':
        with Crontab(**options) as crontab:
            crontab.remove_jobs()
            crontab.add_jobs()
    ... ...

问题1: 就是如果针对某个任务,修改了任务部分配置(这里的配置指的是 CRONJOBS 中配置的) 执行 add or remove时会报错

比如这里有两个任务

CRONJOBS = [
    ('*/1 * * * *', 'jobs.cron.say_hello', [], {}, '>> /tmp/say_hello_v2.txt'),
    ('*/2 * * * *', 'jobs.cron.say_hello', ['james'], {}, '> /tmp/say_hello.txt'),
]

前面已经通过 python manage.py crontab add 添加创建了任务,现在 修改第二个任务的日志输出 为 /tmp/say_hello-modify.txt

然后不管是先执行 crontab add 还是 crontab remove 都会先报个错,然后提示你再次执行 crontab add 就可以了

(temp) [devops@test-xxxx-01-vm /tmp/django_jobs_crontab Mon Mar 11 17:11:02]$ vim django_jobs_crontab/settings.py
(temp) [devops@test-xxxx-01-vm /tmp/django_jobs_crontab Mon Mar 11 17:11:16]$ python manage.py crontab add
removing cronjob: (5e89171a1a9f87fd618b87d1e913d550) -> ('*/1 * * * *', 'jobs.cron.say_hello', [], {}, '>> /tmp/say_hello_v2.txt')
removing cronjob: (1e10640e1aafd33e3d4c47d5ecf0c888) -> ('*/2 * * * *', 'jobs.cron.say_hello', ['james'], {}, '> /tmp/say_hello.txt')
Traceback (most recent call last):
  File "/tmp/django_jobs_crontab/manage.py", line 22, in <module>
    main()
  ... ...
  File "/data/colinspace/.pyenv/versions/temp/lib/python3.9/site-packages/django_crontab/crontab.py", line 171, in __get_job_by_hash
    raise RuntimeError(
RuntimeError: No job with hash 420fc9eb9dac411dd0c17fd6d6b42f84 found. It seems the crontab is out of sync with your settings.CRONJOBS. Run "python manage.py crontab add" again to resolve this issue!

重点在 No job with hash 420fc9eb9dac411dd0c17fd6d6b42f84 found

这个字符串是django-crontab模板给每个人任务生产的唯一ID。

要想知道ID是怎么来的,ID是否其他作用,我们先来看看django-crontab的核心原理


三、django-crontab的实现原理

1、先从django_crontab/management/commands/crontab.py 代码入口

因为目前django-crontab管理任务,都是通过命令行的形式,所以操作入口肯定在 commands下

看到在 Command类 的 handle 方法中通过获取的 subcommand 参数来实现任务的增(add)、查(show)、删(remove)和执行(run) 四个操作

另外有个细节大家需要关注下

实际执行 remove_jobs/add_jobs/show_jobs/run_job 等Crontab类的方法是都是通过 with 实现的。

with使用调用,因为with语句提供了一种简洁的方式来使用上下文管理器,来确保资源的正确获取和释放

关于Python的上下文管理器可以参考文章 《聊聊Python中上下文管理》

关于上下文管理,这里我们知道它是一种用于管理资源的 Python 对象,通过定义 enter() 和 exit() 方法,它可以在进入和退出代码块时执行特定的操作。

2、看到 django_crontab/crontab.py 中对于Crontab类的定义

# django_crontab/crontab.py
class Crontab(object):
    def __init__(self, **option):
        self.verbosity = int(options.get('verbosity', 1))
        self.readonly = options.get('readonly', False)
        self.crontab_lines = []
        self.settings = Settings(settings)

    def __enter__(self):
        self.read()
        return self

    def __exit__(self, type, value, traceback):
        if not self.readonly:
            self.write()
    
    def read(self):
        # 实际是调用 linux 系统 crontab -l 展示结果
        ... ...
    
    def write(self):
        # 实际是读取crontab_lines内容,然后写入到临时文件,然后通过 Linux系统的 crontab tmp_path_file 来把任务写入到当前用户的crontab文件中
        # 一般是 /var/spool/cron/username-xxx
        ... ...

    def add_jobs(self):
        ... ...

    def show_jobs(self):
        ... ...

    def remove_jobs(self):
        ... ...
    
    def run_job(self, job_hash):
        ... ...
    
    def __hash_job(self, job):
        ... ...

    def __get_job_by_hash(self, job_hash):
        ... ...

让我们来分析如上代码

2.1、实现了 enter() 和 exit() 方法,分别是在进入Crontab类和退出的时候执行一些操作

2.2、进入的时候调用了read方法,核心是把当前Linux系统当前用户的任务查出来赋值给self.crontab_lines 变量

2.3、退出的时候,如果readonly 为False的时候,调用write方法 把 self.crontab_lines的值回写到 Linux系统当前用户的任务文件中去

2.4、然后 show_jobsremove_jobs 其实都是操作self.crontab_lines 变量,结合 上下文 来更新 Linux系统当前用户的任务文件

2.5、add_jobs 核心是把 Django settings中配置的CRONJOBS变量的内容以特定的格式(self.settings.CRONTAB_LINE_PATTERN)写入到 self.crontab_lines 变量

所以django-crontab的核心原理就是: 通过读取 Django settings中配置的CRONJOBS变量的内容 以特定的格式写入到self.crontab_lines,然后通过上下文管理来更新 Linux系统当前用户的任务文件


四、django-crontab 的任务ID

在上面分析django-crontab的实现原理中说道 add_jobs 方法按照特定格式写入self.crontab_lines,其中调用了如下代码

self.__hash_job(job)

核心是给每个Job任务,根据job的实际配置来生产一个唯一的ID

def __hash_job(self, job):
    """
    Builds an md5 hash representing the job
    """
    j = json.JSONEncoder(sort_keys=True).encode(job)
    h = hashlib.md5(j.encode('utf-8')).hexdigest()
    return h

为何这里要单独介绍下 任务ID的生成呢,两个点

第一、是前面第二趴介绍 先修改了任务本身,然后执行crontab add or remove遇到问题

是因为任务的ID是根据任务的配置本身来做的md5串,所以修改任务本身任何地方,就会导致任务会有新的ID产生。

因为 crontab add 是先调用 remove_jobs然后调用add_jobs, 在remove_jobs 删除的任务是从 self.crontab_lines来的,然后先从 self.crontab_lines中删除旧的(注意旧的任务ID是旧的)

然后在self.verbosity>=1 时,进行print输出是调用了 self.__get_job_by_hash

def __get_job_by_hash(self, job_hash):
    for job in self.settings.CRONJOBS:
        if self.__hash_job(job) == job_hash:
            return job
    raise RuntimeError(
        'No job with hash %s found. It seems the crontab is out of sync with your settings.CRONJOBS. '
        'Run "python manage.py crontab add" again to resolve this issue!' % job_hash
    )

这是拿新的任务的ID( self.__hash_job(job) )和旧的ID做比较,如果相等怎返回job,否则报错, 新的因为任务本身修改而发生变化,所以ID值肯定发生了变化

第二、这里点留个悬念,后续文章中会涉及到, 是关于运维平台开发统一的任务管理中心时会有介绍


然后回到第二趴说使用django-crontab时的问题

问题2、就是无法单独查看或者删除某个指定ID的任务

虽然每个任务都有了ID,通过 show 可以看到所有任务,但是想只查看/删除 指定ID的任务是无法实现的,只会全部展示或者删除所有任务(从源码执行这两个操作都是遍历循环self.crontab_lines)

当然 run_job 是通过ID获取到job配置,然后获取到django视图函数之后执行该函数。


今天的源码阅读就介绍到这里,相信大家对django-crontab有了更深入的了解。

如果有疑问,随后沟通交流哈。

下篇文章预告 《优化django-crontab实现页面管理任务》


如果你觉得有所收获,欢迎关注"菩提老鹰"进行点赞和喜欢哦~
一起交流,分享知识,快乐生活,我是老鹰,我们下一期见~

标签:...,jobs,self,crontab,django,job,源码
From: https://blog.csdn.net/eaglecolin/article/details/136675255

相关文章

  • 全面解析 qiankun 源码
    本文将针对微前端框架qiankun的源码进行深入解析,在源码讲解之前,我们先来了解一下什么是微前端。微前端是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将单页面前端应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。各个前端应用还可以独立开发、独立......
  • 【前端素材】推荐优质在线绿色有机果蔬商城网页Fulo平台模板(附源码)
    一、需求分析绿色新鲜有机果蔬商城是指一个专门销售绿色、有机、新鲜水果和蔬菜的在线平台,旨在为用户提供优质的、健康的食品购物体验。1、功能分析:绿色新鲜有机果蔬商城是指一个专门销售绿色、有机、新鲜水果和蔬菜的在线平台,旨在为用户提供优质的、健康的食品购物体验。下......
  • 基于微信小程序的场地预约系统设计与实现(源码+lw+部署文档+讲解等)
    文章目录前言项目运行截图技术框架后端采用SpringBoot框架前端框架Vue可行性分析系统测试系统测试的目的系统功能测试数据库表设计代码参考数据库脚本为什么选择我?获取源码前言......
  • 基于微信小程序的宠物寄养平台小程序设计与实现(源码+lw+部署文档+讲解等)
    文章目录前言项目运行截图技术框架后端采用SpringBoot框架前端框架Vue可行性分析系统测试系统测试的目的系统功能测试数据库表设计代码参考数据库脚本为什么选择我?获取源码前言......
  • 鸿蒙开发入门实战案例-菜谱列表(附源码)
    昨天分享了鸿蒙的一些基础组件和布局方式,今天直奔主题,做一个菜谱列表,先看效果:这是实际开发中非常常见的列表样式,对初学者来说可能看起来有一些复杂,没关系,我们先从最简单的列表开始,一步一步实现它。昨天说过List列表组件的基本使用方式:List(){ListItem(){T......
  • 【计算机毕业设计源码】基于OpenCV的人脸检测系统
    项目概况基于OpenCV的人脸检测系统可对人脸进行框线检测,利用OpenCV的检测算法对单个或多个人脸实现框线定位。运行环境基于OpenCV的人脸检测系统运行环境如下:Python:≥3.5OpenCV:≥4.0IDE工具:VisualStudioCode技术栈:Python+OpenCV+PyQt5主要功能基于Ope......
  • 【MATLAB源码-第140期】基于matlab的深度学习的两用户NOMA-OFDM系统信道估计仿真,对比L
    操作环境:MATLAB2022a1、算法描述深度学习技术在无线通信领域的应用越来越广泛,特别是在非正交多址接入(NOMA)和正交频分复用(OFDM)系统中,深度学习技术被用来提高信道估计的性能和效率。信道估计是无线通信系统中的关键技术之一,它直接影响着系统的通信质量和可靠性。本文将详细介......
  • 【MATLAB源码-第146期】基于matlab的信源编码仿真GUI,对比霍夫曼编码,算术编码和LZ编码
    操作环境:MATLAB2022a1、算法描述霍夫曼编码、算术编码和LZ编码是三种广泛应用于数据压缩领域的编码技术。它们各自拥有独特的设计哲学、实现方式和适用场景,因此在压缩效率、编解码速度和内存使用等方面表现出不同的特点。接下来详细描述这三种编码技术,并对它们进行比较。......
  • 【Django开发】前后端分离美多商城项目第1篇:美多商城【附代码文档】
    美多商城项目4.0文档完整教程(附代码资料)主要内容讲述:美多商城,项目准备,商业模式介绍,开发流程,需求分析,项目架构,创建工程,1.在git平台创建工程1.B2B--企业对企业,2.C2C--个人对个人,3.B2C--企业对个人,4.C2B--个人对企业,5.O2O--线上到线下,6.F2C--工厂到个人,7.B2B2C--企业--企业--......
  • 基于Django高校学校校园在线外卖订餐系统设计与实现(Pycharm+Python+Mysql)
     博主介绍:黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。所有项目都配有从入门到精通的基础知识视频课程,学习后应对毕业设计答辩。项目配有对应开发文档、开题报告、任务书、P......