【Django功能开发】如何正确使用定时任务(启动、停止)

news/2024/4/25 16:49:53/文章来源:https://blog.csdn.net/qq_15028721/article/details/129254967

系列文章目录

【Django开发入门】ORM的增删改查和批量操作
【Django功能开发】编写自定义manage命令


文章目录

  • 系列文章目录
  • 前言
  • 一、django定时任务
  • 二、django-apscheduler基本使用
    • 1.安装django-apscheduler
    • 2.配置settings.py的INSTALLED_APPS
    • 3.通过命令生成定时记录表
    • 3.如何创建自定义manage命令
    • 4.创建runapscheduler.py文件
    • 5.修改任务,上一个定时将被清空
    • 6.系统中启动和停止定时
    • 7.如何记录进程id
    • 8.对自定义manage命令添加参数,控制定时任务的开启和停止
  • 二、django-apscheduler参数应用
    • 1.jobstore作业存储
    • 2.scheduler调度器
    • 3.executor执行器
    • 4.trigger触发器
    • 5.job任务管理
      • 第一种方式:调度器条用add_job方法
      • 第二种方式:装饰器执行
    • 6.监听定时任务
  • 总结


前言

顾名思义,定时任务是会在后台一直运行的,但是在使用过程中,我们还是会更新程序的,尤其是在刚开始写定时任务时,会频繁的启动定时程序,但是这样可能有问题的,每次启动程序都是打开了新的定时进程,前边的定时程序可能没有关闭,还在默默的帮你完成之前设定的工作(需要看实际情况)。
网络上虽然有很多教程,其实使用方式都有些问题,真的不敢直接用。这里整理了我自己在django框架中使用定时程序的一点心得,如有需要可自取。


提示:以下是本篇文章正文内容,下面案例可供参考

一、django定时任务

在百度上随便一搜 django定时任务,有很多库都实现了定时任务,比如django-crontab、Celery、django-apscheduler(apscheduler)、time自定义等这些python库,如果在windows系统还可以使用系统自带的定时任务,linux系统自带的crontab任务。
上述这些都可以实现定时任务,在开发中也可能都应用过,本篇博客介绍的是在django框架下开发定时功能,我这里推荐使用的是django-apscheduler,适用于中小系统定时任务功能。

定时任务描述
crontab适用于linux系统
django-crontab适用于linux系统,基于crontab
Celery适用于linux系统,任务队列,大型项目
windows定时适用于windows系统
time适用于多种系统
django-apscheduler适用于多种系统,中小型项目

二、django-apscheduler基本使用

1.安装django-apscheduler

代码如下(示例):

pip install django-apscheduler

2.配置settings.py的INSTALLED_APPS

代码如下(示例):

INSTALLED_APPS = (# ..."django_apscheduler",
)

3.通过命令生成定时记录表

使用python的manage命令,我们应该cd到项目目录下,就是manage.py文件所在的目录。
在这里插入图片描述

我们应该使用python manage.py makemigrations 和 python manage.py migrate同步数据库,数据库中将生成2个表,django_apscheduler_djangojob和django_apscheduler_djangojobexecution。
在这里插入图片描述

3.如何创建自定义manage命令

自定义命令整理中

4.创建runapscheduler.py文件

runapscheduler.py正是通过自定义创建manange命令的py文件,可以通过python manage.py runapscheduler 启动定时程序。

import loggingfrom django.conf import settingsfrom apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.cron import CronTrigger
from django.core.management.base import BaseCommand
from django_apscheduler.jobstores import DjangoJobStore
from django_apscheduler.models import DjangoJobExecution
from django_apscheduler import utillogger = logging.getLogger(__name__)def my_job():# Your job processing logic here...print(123)passdef delete_old_job_executions(max_age=604_800):"""此作业从数据库中删除早于“max_age”的APScheduler作业执行条目。它有助于防止数据库中塞满不再有用的旧历史记录。最长7天"""DjangoJobExecution.objects.delete_old_job_executions(max_age)class Command(BaseCommand):help = "Runs APScheduler."def handle(self, *args, **options):scheduler = BlockingScheduler(timezone=settings.TIME_ZONE)scheduler.add_jobstore(DjangoJobStore(), "default")scheduler.add_job(my_job,trigger=CronTrigger(second="*/10"),  # Every 10 secondsid="my_job",  # The `id` assigned to each job MUST be uniquemax_instances=1,replace_existing=True,)logger.info("Added job 'my_job'.")scheduler.add_job(delete_old_job_executions,trigger=CronTrigger(day_of_week="mon", hour="00", minute="00"),  # Midnight on Monday, before start of the next work week.id="delete_old_job_executions",max_instances=1,replace_existing=True,)logger.info("Added weekly job: 'delete_old_job_executions'.")try:logger.info("Starting scheduler...")scheduler.start()except KeyboardInterrupt:logger.info("Stopping scheduler...")scheduler.shutdown()logger.info("Scheduler shut down successfully!")

1234这4步是django-apscheduler官网的使用步骤,经过测试,定时程序已经正常运行了。
在这里插入图片描述
现在,数据库中已经有了相关定时任务的记录。
在这里插入图片描述
在这里插入图片描述

5.修改任务,上一个定时将被清空

将步骤4中的runapscheduler文件的my_job改成my_job2,再次python manage.py runapscheduler。
修改的位置
在这里插入图片描述
在这里插入图片描述

新的定时任务和数据库记录如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.系统中启动和停止定时

在linux系统中,我们希望定时任务后台运行,需要执行python manage.py runapscheduler &。
其实,通过python manage.py命令启动的程序,每次都是开启了一个新的进程,进程中开启一个线程去处理定时任务。这样启动的定时任务跟django的web服务是分开,相互之间影像很低。很多博客将定时卸载views.py文件开始位置,定时程序和web服务是在一个进程上,会出现阻塞的情况。
因为某些原因,我们想关闭定时程序,在命令行输入ps -aux | grep python可以查看通过python运行的程序,并且可以查看是哪一个py文件,我的自定义命令文件是start_crontab.py,这里就找start_crontab.py,在通过kill 命令停止该进程。

ps -aux | grep python
# 下图的红框就是我们的启动命令,蓝框是进程id列,725066就是我们定时任务进程id
kill 725066

在这里插入图片描述

7.如何记录进程id

其实无论实在linux还是在windows,我们是可以记录python manage.py runapscheduler任务的进程id的,下边代码会生成一个crontab_pid.txt文件,记录进程id,方便下一次处理和操作。

import osfrom apscheduler.schedulers.blocking import BlockingScheduler
from django.core.management import BaseCommandfrom feishuapi.tasks import mission_6min
from tianyiapi.settings import BASE_DIRclass Command(BaseCommand):# 帮助文本, 一般备注命令的用途及如何使用。help = "更新已有任务的状态"# 处理命令行参数,可选def add_arguments(self, parser):passdef kill(self, pid):# 本函数用于中止传入pid所对应的进程if os.name == 'nt':# Windows系统cmd = 'taskkill /pid ' + str(pid) + ' /f'try:os.system(cmd)print(pid, 'killed')except Exception as e:print(e)elif os.name == 'posix':# Linux系统cmd = 'kill ' + str(pid)try:os.system(cmd)print(pid, 'killed')except Exception as e:print(e)else:print('Undefined os.name')# 核心业务逻辑def handle(self, *args, **options):# 1.读取上次保存的pidfile = os.path.join(BASE_DIR, 'crontab_pid.txt')if os.path.isfile(file):with open(file, 'r') as f:pid = f.read()# 2.如果存在杀死上一次的进程# print('上一次进程', pid)if pid:# 调用kill函数,终止进程self.kill(pid=pid)with open(file, 'w+') as f:# 3.获取当前进程的pidpid = os.getpid()# print('当前进程的pid: ', pid)f.write(pid.__str__())try:# 创建调度器BlockingScheduler()scheduler = BlockingScheduler()# 添加任务,时间间隔为6分钟scheduler.add_job(mission_6min, 'interval', minutes=6, id='test_job1')scheduler.start()except Exception as e:print(e)print('定时任务已启动')

8.对自定义manage命令添加参数,控制定时任务的开启和停止

这个目前还没做,有时间再补上。

二、django-apscheduler参数应用

django-apscheduler和apscheduler一样,我们使用的过程中需要根据不同的场景调整定时任务。

1.jobstore作业存储

        scheduler = BlockingScheduler(timezone=settings.TIME_ZONE)scheduler.add_jobstore(DjangoJobStore(), "default")

2.scheduler调度器

BlockingScheduler : 当调度器是你应用中唯一要运行的东西时

BackgroundScheduler : 当你没有运行任何其他框架并希望调度器在你应用的后台执行时使用。

AsyncIOScheduler : 当你的程序使用了asyncio(一个异步框架)的时候使用。

GeventScheduler : 当你的程序使用了gevent(高性能的Python并发框架)的时候使用。

TornadoScheduler : 当你的程序基于Tornado(一个web框架)的时候使用。

TwistedScheduler : 当你的程序使用了Twisted(一个异步框架)的时候使用

QtScheduler : 如果你的应用是一个Qt应用的时候可以使用。

from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.schedulers.background import BackgroundSchedulerscheduler = BackgroundScheduler()
scheduler.start()  # 此处程序不会发生阻塞scheduler = BlockingScheduler()
scheduler.start()  # 此处程序会发生阻塞

3.executor执行器

通常都是使用默认值,特殊需求可以考虑。

# 方式1: 线程
from apscheduler.executors.pool import ThreadPoolExecutor
executors = {'default': ThreadPoolExecutor(20)   # 最多20个线程同时执行
}
scheduler = BackgroundScheduler(executors=executors)# 方式2: 进程
from apscheduler.executors.pool import ProcessPoolExecutor
executors = {'default': ProcessPoolExecutor(3)  # 最多3个进程同时运行
}
scheduler = BackgroundScheduler(executors=executors)

4.trigger触发器

APScheduler 有三种内建的 trigger:

date: 特定的时间点触发
interval: 固定时间间隔触发
cron: 在特定时间周期性地触发

from datetime import date# 在2020年11月11日00:00:00执行
sched.add_job(my_job, 'date', run_date=date(2020, 11, 11))# 在2020年11月1日16:30:05
sched.add_job(my_job, 'date', run_date=datetime(2020, 11, 11, 16, 30, 5))
sched.add_job(my_job, 'date', run_date='2009-11-06 16:30:05')# 立即执行
sched.add_job(my_job, 'date')  
sched.start()
from datetime import datetime# 时间间隔可选seconds 、minutes、hours、days、weeks、start_date、end_date 、timezone
# 每两小时执行一次
sched.add_job(job_function, 'interval', hours=2)# 在2010年10月10日09:30:00 到2014年6月15日的时间内,每两小时执行一次
sched.add_job(job_function, 'interval', hours=2, start_date='2010-10-10 09:30:00', end_date='2014-06-15 11:00:00')
# 可选周期second、minute、hour、day、day_of_week、month、year、start_date、end_date、timezone
# 在6、7、8、11、12月的第三个周五的00:00, 01:00, 02:00和03:00 执行
sched.add_job(job_function, 'cron', month='6-8,11-12', day='3rd fri', hour='0-3')# 在2014年5月30日前的周一到周五的5:30执行
sched.add_job(job_function, 'cron', day_of_week='mon-fri', hour=5, minute=30, end_date='2014-05-30')

5.job任务管理

通常添加job有2中方式。

第一种方式:调度器条用add_job方法

def my_job():# Your job processing logic here...print(123)pass
job = scheduler.add_job(my_job, 'interval', minutes=2)  # 添加任务

第二种方式:装饰器执行

scheduler = BlockingScheduler(timezone=settings.TIME_ZONE)
scheduler.add_jobstore(DjangoJobStore(), "default")
@register_job(scheduler, "interval", seconds=1)
def dummy_job():print("I'm a job!")
scheduler.start()

涉及到具体定时任务,可以通过id参数进行管理。

# 方式1: 通过对象
job = scheduler.add_job(myfunc, 'interval', minutes=2)  # 添加任务
job.remove()  # 移除任务
job.pause() # 暂停任务
job.resume()  # 恢复任务# 方式2: 通过任务id
scheduler.add_job(myfunc, 'interval', minutes=2, id='my_job_id')  # 添加任务    
scheduler.remove_job('my_job_id')  # 移除任务
scheduler.pause_job('my_job_id')  # 暂停任务
scheduler.resume_job('my_job_id')  # 恢复任务scheduler.shutdown()  # 停止任务

6.监听定时任务

# coding:utf-8from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.events import EVENT_JOB_EXECUTED, EVENT_JOB_ERROR, EVENT_JOB_MISSED
import datetime
import logginglogger = logging.getLogger('job')
logging.basicConfig(level=logging.INFO,format = '%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',datefmt = '%Y-%m-%d %H:%M:%S',filename = 'mylog.txt',filemode = 'a')'''任务1'''
def my_job(x):print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), x)'''任务2'''
def test_job(x):print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), x)print(1 / 0)def job_listener(Event):job = scheduler.get_job(Event.job_id)if not Event.exception:print('任务正常运行!')logger.info("jobname=%s|jobtrigger=%s|jobtime=%s|retval=%s", job.name, job.trigger,Event.scheduled_run_time, Event.retval)else:print("任务出错了!!!!!")logger.error("jobname=%s|jobtrigger=%s|errcode=%s|exception=[%s]|traceback=[%s]|scheduled_time=%s", job.name,job.trigger, Event.code,Event.exception, Event.traceback, Event.scheduled_run_time)scheduler = BlockingScheduler()
scheduler.add_job(func=test_job, args=('一次性任务,会出错',),next_run_time=datetime.datetime.now() + datetime.timedelta(seconds=15), id='date_task')
scheduler.add_job(func=my_job, args=('循环任务',), trigger='interval', seconds=3, id='interval_task')
scheduler.add_listener(job_listener, EVENT_JOB_ERROR | EVENT_JOB_MISSED | EVENT_JOB_EXECUTED)
scheduler._logger = logging
scheduler.start()

总结

以上就是我对定时任务的理解,在接下来的工作中可以更好的应用定时任务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_75400.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式 linux 系统开发网络的设置

目录 一、前言 二、linux网络静态地址设置 前言 为什么要对linux系统下的ubuntu进行网络设置呢? 因为我们在嵌入式开发中,我们要保证windows系统、linux系统、开发板的ip要处于同一个网段,而默认ubuntu下的linux系统的ip是动态分配的&#…

如何彻底删除SQL Server 2008中的登录账号

我个人遇到的最烦人的事情之一是 SQL Server Management Studio中“服务器名称和登录名”对话框的下拉列表。 以下是我想从 SSMS 连接屏幕中删除某些内容的两种情况: 键入的服务器名称不正确 服务器将来不需要。当我看到服务器的名称,它已经存在了很长一段时间,我知道我不会…

图像处理实战--Opencv实现人像迁移

前言: Hello大家好,我是Dream。 今天来学习一下如何使用Opencv实现人像迁移,欢迎大家一起参与探讨交流~ 本文目录:一、实验要求二、实验环境三、实验原理及操作1.照片准备2.图像增强3.实现美颜功能4.背景虚化5.图像二值化处理6.人…

Day21【元宇宙的实践构想07】—— 元宇宙与人工智能

💃🏼 本人简介:男 👶🏼 年龄:18 🤞 作者:那就叫我亮亮叭 📕 专栏:元宇宙 0.0 写在前面 “元宇宙”在2021年成为时髦的概念。元宇宙到底是什么?元宇…

【论文笔记】Decoupling Representation and Classifier for Long-Tailed Recognition

这一篇其实并不是提出什么新的东西,而且是做了点类似综述的技术调用实验。省流:T-normalization最好用 摘要 现状:Existing solutions usually involve class-balancing strategies, e.g. by loss re-weighting, data re-sampling, or tran…

高燃!GitHub上标星75k+超牛的Java面试突击版

前言不论是校招还是社招都避免不了各种面试。笔试,如何去准备这些东西就显得格外重要。不论是笔试还是面试都是有章可循的,我这个有章可循‘说的意思只是说应对技术面试是可以提前准备。运筹帷幄之后,决胜千里之外!不打毫无准备的仗,我觉得大…

扒系统CR8记录

目录 终极改造目标 过程记录 参考 为了将一套在线安装的系统,在不了解其架构、各模块细节的基础上,进行扒弄清楚,作以下记录。 终极改造目标 最终的目标,就是只通过CreMedia8_20230207.tar.gz解压 install 就把业务包安装了&…

安装VMWare虚拟机之后,发现网络贼卡,打开网页很慢

事情描述: 最近忙一个项目,需要到虚拟机中部署环境,安装完之后,就开整自己的项目了。 可以过几天,发现本地网络贼卡,打开各网页慢的一批,一开始还以为是路由器的问题,反复折腾之后排…

[12]云计算概念、技术与架构Thomas Erl-第5章 云使能技术

目录 第五章 云使能技术 5.1宽带网络和Internet架构 5.1.1Internet服务提供者(ISP) 5.1.2无连接分组(数据报网络) 5.1.3基于路由器的互联 5.1.4技术和商业考量 总结 5.2数据中心技术 5.2.1虚拟化 5.2.2标准化与模块化 …

微服务实战01-maven聚合工程

接下来的一段时间,我们将要来学习微服务,本着重实战的原则,你不需要去深究一些相关的原理,只要能跟着教程一步一步做下来,就可以快速地掌握Java微服务开发技巧。 我们学习微服务的第一步,就是要知道怎么创…

VMware安装FreeBSD虚拟机

1. 下载FreeBSD镜像地址 国内阿里云下载地址: freebsd-releases-ISO-IMAGES安装包下载_开源镜像站-阿里云 选择自己需要的版本下载。 2. 创建FreeBSD虚拟机 2.1. 选择操作系统类型 2.2. 导入FreeBSD镜像 3. 安装FreeBSD 第1步:保持默认让其自动进入…

基于vscode开发vue项目的详细步骤教程

1、Vue下载安装步骤的详细教程(亲测有效) 1_水w的博客-CSDN博客 2、Vue下载安装步骤的详细教程(亲测有效) 2 安装与创建默认项目_水w的博客-CSDN博客 目录 五、vscode集成npm开发vue项目 1、vscode安装所需要的插件: 2、搭建一个vue小页面(入门vue) 3、大致理解…

【音视频开发】 ffmpeg解码API

1.版本迭代ffmpeg解码API经过了好几个版本的迭代,上一个版本的API是解码视频:avcodec_decode_video2解码音频:avcodec_decode_audio4我们现在能看到的很多解码例子用的都是这两个,不过现在ffmpeg更推荐用新一代的API向解码器输送数…

优秀的IC/FPGA开源项目(六)-手语字母翻译器

《优秀的IC/FPGA开源项目》是新开的系列,旨在介绍单一项目,会比《优秀的 Verilog/FPGA开源项目》内容介绍更加详细,包括但不限于综合、上板测试等。两者相辅相成,互补互充~一种智能手套,可将手语字母翻译成带显示器的书…

Studio One6最新版免费的电脑DAW宿主音乐软件

Studio One 6是一款非常专业的音乐创作编辑软件。为用户提供了所有一切你所需要创作的功能,包括所有的歌曲、项目、仪表板等动能,而且还自定义添加配置文件,良好的界面交互和丰富的功能板块。Studio One是一款DAW宿主音乐软件。用于创建&…

数字IC笔试题---千题解,量大管饱,图文并茂

前言出笔试题汇总,是为了总结秋招可能遇到的问题,做题不是目的,在做题的过程中发现自己的漏洞,巩固基础才是目的。所有题目结果和解释由笔者给出,答案主观性较强,若有错误欢迎评论区指出,资料整…

【MySQL之SQL语法篇】系统学习MySQL,从应用SQL语法到底层知识讲解,这将是你见过最完成的知识体系

文章目录一、数据管理技术的三个阶段二、SQL语句学习1. DCL数据控制语言1.1 创建用户1.2 修改用户名1.3 修改密码1.4 删除用户1.5 授权1.6 查看权限1.7 回收权限2. DDL数据定义语言2.1 操作数据库2.2 操作数据表2.3 操作数据3. DQL数据查询语言基本语法3.1 单表查询3.1.1选择表…

Qt::QOpenGLWidget 渲染天空壳

在qt窗口中嵌入opengl渲染天空壳和各种立方体一 学前知识天空壳的渲染学前小知识1 立方体贴图 天空壳的渲染就是利用立方体贴图来实现渲染流程2 基础光照 光照模型3 opengl帧缓冲 如何自定义帧缓冲实现后期特效4 glsl常见的shader内置函数 glsl编程常用的内置函数二 shader代码…

某建筑设计研究院“综合布线管理软件”应用实践

某建筑设计研究院有限公司(简称“某院”)隶属于国务院国资委直属的大型骨干科技型中央企业。“某院”前身为中央直属设计公司,创建于1952年。成立近70年来,始终秉承优良传统,致力于推进国内勘察设计产业的创新发展&…

02-MyBatis查询-

文章目录Mybatis查询1,配置文件实现CRUD1.1 环境准备Debug01: 别名mybatisx报错1.2 查询所有数据1.2.1 编写接口方法1.2.2 编写SQL语句1.2.3 编写测试方法1.2.4 起别名解决上述问题1.2.5 使用resultMap解决上述问题1.2.6 小结1.3 查询详情1.3.1 编写接口方法1.3.2 编…