今天搞了一天 终于搞出来了 ,后边改造的话,就可以把系统计划任务搞到Django里面,网上文章很乱,后边代码都是自己验证的 ,赶紧记录下来。
django-apscheduler
支持三种调度任务:固定时间间隔,固定时间点(日期),Crontab 命令。同时,它还支持异步执行、后台执行调度任务 配置简单、功能齐全、使用灵活、支持windows和linux,适合中小型项目。
基础组件
APScheduler 有四种组件,分别是:
调度器(scheduler),
作业存储(job store),
触发器(trigger),
执行器(executor)。
schedulers(调度器)
它提供 7 种调度器,能够满足我们各种场景的需要。例如:后台执行某个操作,异步执行操作等。调度器分别是:
triggers(触发器)
date 触发器 作业任务只会执行一次。它表示特定的时间点触发。它的参数如下:
run_date (datetime 或 str) 作业的运行日期或时间
timezone (datetime.tzinfo 或 str) 指定时区
interval 触发器 固定时间间隔触发。interval 间隔调度,参数如下:
weeks (int) 间隔几周
days (int) 间隔几天
hours (int) 间隔几小时
minutes (int) 间隔几分钟
seconds (int) 间隔多少秒
start_date (datetime 或 str) 开始日期
end_date (datetime 或 str) 结束日期
timezone (datetime.tzinfo 或str) 时区
cron 触发器 在特定时间周期性地触发,和Linux crontab格式兼容。
参数 说明
year (int 或 str) 年,4位数字
month (int 或 str) 月 (范围1-12)
day (int 或 str) 日 (范围1-31
week (int 或 str) 周 (范围1-53)
day_of_week (int 或 str) 周内第几天或者星期几 (范围0-6 或者 mon,tue,wed,thu,fri,sat,sun)
hour (int 或 str) 时 (范围0-23)
minute (int 或 str) 分 (范围0-59)
second (int 或 str) 秒 (范围0-59)
start_date (datetime 或 str) 最早开始日期(包含)
end_date (datetime 或 str) 最晚结束时间(包含)
timezone (datetime.tzinfo 或str) 指定时区
表达式类型
表达式 参数类型 描述
作业存储(job store)
有两种添加方法,其中一种是 add_job(), 另一种则是@register_job()修饰器来修饰函数。
这个两种办法的区别是:第一种方法返回一个 Job 的实例,可以用来改变或者移除 job。第二种方法只适用于应用运行期间不会改变的 job。
django-apscheduler框架还提供了很多操作定时任务的函数。比如:
删除任务
scheduler.remove_job(job_name)
暂停任务
scheduler.pause_job(job_name)
开启任务
scheduler.resume_job(job_name)
获取所有任务
scheduler.get_jobs()
修改任务
scheduler.modify_job(job_name)
注:修改任务只能修改参数,如果要修改执行时间的话,有3种方法
第一就把任务删了重新创建,
第二直接操作数据库,
第三用到下面重设任务。
重设任务
scheduler.reschedule_job(job_name)
scheduler.reschedule_job(job_id=“job1”, trigger=‘interval’, minutes=1)
执行器(executor)
执行调度任务的模块。最常用的 executor 是 ThreadPoolExecutor,存储路径是在Django数据库中
说了这么多 上个代码吧
安装
pip3 install django-apscheduler
配置
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_apscheduler',
]
把django_apscheduler弄进来,然后要做下迁移 。
测试发现,多个任务的话 ,sqlite3 存在数据库锁住的问题,因为sqlite3只能1个写入,不能多个写入。
所以我就给改成MySQL了
DATABASES = {
'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
# 配置连接数据库 ,导入pymysql类库
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django',
'HOST': 'ip',
'PORT': 3306,
'USER': 'root',
'PASSWORD': 'password'
}
}
改成MySQL还一个问题,要在项目的__init__.py里面加上
#import pymysql
#pymysql.install_as_MySQLdb()
不然 连接数据库又是问题,这样就可以迁移了
20220408更新
加上放服务器上不好使,还得安装mysqlclient
apt-get install libmariadbd-dev
pip3 install myqlclient
python manage.py migrate
代码业务逻辑
然后建议你新建一个应用,在新应用的视图(view)里就可以写定时任务的逻辑了
from django.http import HttpResponse
from django.shortcuts import render
# Create your views here.
import time
from apscheduler.schedulers.background import BackgroundScheduler
from django_apscheduler.jobstores import DjangoJobStore, register_job, register_events
print('django-apscheduler')
def job2(name):
# 具体要执行的代码
print('{} 任务运行成功!{}'.format(name, time.strftime("%Y-%m-%d %H:%M:%S")))
def job3(name):
print('{} 任务运行成功!{}'.format(name, time.strftime("%Y-%m-%d %H:%M:%S")))
# 实例化调度器
scheduler = BackgroundScheduler(timezone='Asia/Shanghai') # 这个地方要加上时间,不然他有时间的警告
# 调度器使用DjangoJobStore()
scheduler.add_jobstore(DjangoJobStore(), "default")
# 添加任务1
# 每隔5s执行这个任务,这个就是装饰器的玩法
@register_job(scheduler, "interval", seconds=5, args=['老K'], id='job1', replace_existing=True)
def job1(name):
# 具体要执行的代码
print('{} 任务运行成功!{}'.format(name, time.strftime("%Y-%m-%d %H:%M:%S")))
# 下面这就是add_job的方式 interval
scheduler.add_job(job2, "interval", seconds=10, args=['老Y'], id="job2", replace_existing=True)
# 下面这就是add_job的方式 crontab 16点 38分 40分执行
scheduler.add_job(job3, 'cron', hour='16', minute='38,40', args=['鬼人'], id='job3', replace_existing=True)
"""
20220408更新
id可以不加,如果不加ID是这个应用view下的函数名字
replace_existing=True 这个东西不加的话,他会提示ID冲突了,我查了好多文章,把这答案找出来了 。
"""
# 监控任务
register_events(scheduler) # 这个event 这个会有已经被废弃的用法删除线,我不知道这个删除了 ,还会不会好用
# 调度器开始运行
scheduler.start()
def index(request):
return HttpResponse('ok')
运行
这运行的时候,我一开始都是
python manager.py runserver
今天弄的时候 ,代码写的有问题了,然后这货都停不下来了 ,ctrl c都不好使
后来想了一招,给Django添加一个run 让他可以右键运行
在整个项目下面添加一个runner.py
import os
if __name__ == '__main__':
os.system('python manage.py runserver')
右键就可以运行django项目了