Django 使用定时任务


前言

Windows 系统进行 Django 开发工作,然后原来使用的django-crontab插件没办法在Windows系统上面进行定时任务。因此又想了其他方式来实现定时任务。下面就来说说这些方案的优缺点。


使用django-crontab插件来实现定时任务

安装庫

pip install django-crontab

注冊app

在settings.py中的 INSTALLED_APPS注冊app

INSTALLED_APPS = [
    ...
    'django_crontab'
]

在settings.py中配置定时任务

"""
# 元素的第一个参数是 频次(多久一次)
*  *  *  * *
分 时 日 月 周    命令

M: 分钟(0-59)。每分钟用 * 或者 */1 表示
H:小时(0-23)。(0表示0点)
D:天(1-31)。
m: 月(1-12)。
d: 一星期内的天(0~6,0为星期天)。

*/5 * * * * ---- 每5分鐘執行一次

# 元素的第二个参数是 定时任务(函数)

finally run this command to add all defined jobs from CRONJOBS to crontab (of the user which you are running this command with):
在終端運行: python manage.py crontab add

show current active jobs of this project:
在終端運行: python manage.py crontab show

removing all defined jobs is straight forward:
在終端運行: python manage.py crontab remove
"""
crontab 只在Linux下才能使用
CRONJOBS = [
    ('*/5 * * * *', 'myapp.cron.my_scheduled_job', ' >> /tmp/logs/confdict_handle.log')
]

编写定时任务方法

在子應用新建 crontabs.py 文件,寫入定时任务

import datetime

# 定时任务
def confdict_handle():
    try:
        loca_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        print('本地时间:'+str(loca_time))
    except Exception as e:
        print('发生错误,错误信息为:', e)

使用&运行

开启定时器

python manage.py crontab add

查看开启的定时器

python manage.py crontab show

关闭定时器

python manage.py crontab remove

优缺点

优点:
简单、方便、易于管理和django服务是分离的,不会影响到django对外提供的web服务。
缺点:
无法在Windows平台上运行
官方文檔:
在这里插入图片描述

就算在Linux系统上,也可能出现运行了没有效果的消息,至今未知原因

使用django-apscheduler插件实现定时任务

安装庫

pip install django-apscheduler

注冊app

修改settings.py

INSTALLED_APPS = (
  ...
  "django_apscheduler",
)

迁移数据库

因为django-apscheduler会创建表来存储定时任务的一些信息,所以将app加入之后需要迁移数据

python manage.py migrate

完整示例 在views.py中增加你的定时任务代码

from apscheduler.schedulers.background import BackgroundScheduler # 使用它可以使你的定时任务在后台运行
from django_apscheduler.jobstores import DjangoJobStore, register_events, register_job
import time
'''
date:在您希望在某个特定时间仅运行一次作业时使用
interval:当您要以固定的时间间隔运行作业时使用
cron:以crontab的方式运行定时任务
minutes:设置以分钟为单位的定时器
seconds:设置以秒为单位的定时器
'''

try:
    scheduler = BackgroundScheduler()
    scheduler.add_jobstore(DjangoJobStore(), "default")

    @register_job(scheduler, "interval", seconds=5)
    def test_job():
        # 定时每5秒执行一次
        print(time.strftime('%Y-%m-%d %H:%M:%S'))

    register_events(scheduler)
    # 启动定时器
    scheduler.start()
except Exception as e:
    print('定时任务异常:%s' % str(e))

使用&运行

apscheduler定时任务会跟随django项目一起运行因此直接启动django即可

python manage.py runserver

詳細查看另一篇文章: django-apscheduler

优缺点

优点:
简单、定时方式丰富、轻量
缺点:
定时任务会跟随django项目一起运行,会影响django对外提供的web服务
使用uwsgi线上运行时,很难启动apscheduler定时任务
按照文档上的设置–enable-threads依然没有正常启动,具体原因未知,也查了很多方法,都没有解决。并且也不建议将定时任务和uwsgi放在一起运行,这样定时任务在运行过程中可能会影响uwsgi的服务。

使用Celery插件实现定时任务

介紹

"""
生产者(任务,函数)
    @app.task
    def celery_send_sms_code(mobie,code):

        CCP().send_template_sms(mobie,[code,5],1)


    app.autodiscover_tasks(['celery_tasks.sms'])
消费者
    celery -A proj worker -l INFO

    在虚拟环境下执行指令
    celery -A celery实例的脚本路径 worker -l INFO

    本案例使用
    celery -A celery_tasks.main worker -l INFO

队列(中间人、经纪人)
    #2. 设置broker
    # 我们通过加载配置文件来设置broker
    app.config_from_object('celery_tasks.config')

    # 配置信息 key=value
    # 我们指定 redis为我们的broker(中间人,经纪人,队列)
    broker_url="redis://127.0.0.0:6379/15"

Celery -- 将这3者实现了。

    # 0. 为celery的运行 设置Django的环境
    import os
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'meiduo_mall.settings')

    # 1. 创建celery实例
    from celery import Celery
    # 参数1: main 设置脚本路径就可以了。 脚本路径是唯一的
    app=Celery('celery_tasks')
"""

安装庫

本例建立在认为你已经知道如何使用Celery实现异步任务的基础上,需要学习的请移步Django使用Celery,可參考另一篇博客:celery异步—生产者消费者,或者官方文檔:官方文檔
本例使用redis作为Borker和backend

pip install -U "celery[redis]"

配置celery

settings.py 增加以下代码

# Celery配置
from kombu import Exchange, Queue
# 设置任务接受的类型,默认是{'json'}
CELERY_ACCEPT_CONTENT = ['application/json']
# 设置task任务序列列化为json
CELERY_TASK_SERIALIZER = 'json'
# 请任务接受后存储时的类型
CELERY_RESULT_SERIALIZER = 'json'
# 时间格式化为中国时间
CELERY_TIMEZONE = 'Asia/Shanghai'
# 是否使用UTC时间
CELERY_ENABLE_UTC = False
# 指定borker为redis 如果指定rabbitmq CELERY_BROKER_URL = 'amqp://guest:guest@localhost:5672//'
CELERY_BROKER_URL = 'redis://127.0.0.1:6379/0'
# 指定存储结果的地方,支持使用rpc、数据库、redis等等,具体可参考文档 # CELERY_RESULT_BACKEND = 'db+mysql://scott:tiger@localhost/foo' # mysql 作为后端数据库
CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/1'
# 设置任务过期时间 默认是一天,为None或0 表示永不过期
CELERY_TASK_RESULT_EXPIRES = 60 * 60 * 24
# 设置worker并发数,默认是cpu核心数
# CELERYD_CONCURRENCY = 12
# 设置每个worker最大任务数
CELERYD_MAX_TASKS_PER_CHILD = 100
# 指定任务的位置
CELERY_IMPORTS = (
    'base.tasks',
)
# 使用beat启动Celery定时任务
# schedule时间的具体设定参考:https://docs.celeryproject.org/en/stable/userguide/periodic-tasks.html
CELERYBEAT_SCHEDULE = {
    'add-every-10-seconds': {
        'task': 'base.tasks.cheduler_task',
        'schedule': 10,
        'args': ('hello', )
    },
}

编写定时任务代码

在本例中是在子應用新建 tasks.py 在裏面增加的定时任务

# Create your tasks here
from __future__ import absolute_import, unicode_literals
from celery import shared_task
import time

@shared_task
def cheduler_task(name):
    print(name)
    print(time.strftime('%X'))

使用&运行

启动定时任务

celery -A dase_django_api beat -l info

启动Celery worker 用来执行定时任务

celery -A dase_django_api worker -l -l info

注意:这里的 dase_django_api 要换成你的Celery APP的名称

优缺点

优点
稳定可靠、管理方便
高性能、支持分布式
缺点:
实现复杂
部署复杂
非轻量级

自建代码实现定时任务

创建定时任务

在子應用下创建一个文件名为 schedules.py,键入以下内容

import os, sys, time, datetime
import threading
import django
base_apth = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# print(base_apth)
# 将项目路径加入到系统path中,这样在导入模型等模块时就不会报模块找不到了
sys.path.append(base_apth)
os.environ['DJANGO_SETTINGS_MODULE'] ='base_django_api.settings' # 注意:base_django_api 是我的模块名,你在使用时需要跟换为你的模块
django.setup()
from base.models import ConfDict

def confdict_handle():
    while True:
        try:
            loca_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            print('本地时间:'+str(loca_time))
            time.sleep(10)
        except Exception as e:
            print('发生错误,错误信息为:', e)
            continue


def main():
    '''
    主函数,用于启动所有定时任务,因为当前定时任务是手动实现,因此可以自由发挥
    '''
    try:
        # 启动定时任务,多个任务时,使用多线程
        task1 = threading.Thread(target=confdict_handle)
        task1.start()
    except Exception as e:
        print('发生异常:%s' % str(e))

if __name__ == '__main__':
    main()

使用&运行

直接运行脚本即可

python apps/base/schedules.py

注意:apps/base 為你的子應用路徑

优缺点

优点:
自定义
高度自由
缺点:
过于简单
当任务过多时,占用资源也会增加


Django使用Celery和django-celery-beat可以实现定时任务或周期性任务。下面是两种添加定时任务的方式: 1. 在celery.py中添加任务: 在你的项目中的celery.py文件中,你可以定义定时任务。首先,确保你已经安装了django-celery-beat,并将其添加到INSTALLED_APPS中。然后,在celery.py文件中添加以下代码: ```python from celery import Celery from django.conf import settings app = Celery('your_project_name') app.config_from_object('django.conf:settings', namespace='CELERY') app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) @app.on_after_configure.connect def setup_periodic_tasks(sender, **kwargs): # 添加定时任务 sender.add_periodic_task(10.0, your_task.s(), name='your_task_name') @app.task def your_task(): # 定时任务的具体逻辑 pass ``` 在上面的代码中,`your_project_name`是你的项目名称,`your_task_name`是你给定时任务起的名字,`your_task`是你要执行的具体任务。 2. 通过Django admin后台添加任务: django-celery-beat还提供了通过Django admin后台添加定时任务的方式。首先,在settings.py文件中添加`'django_celery_beat'`到INSTALLED_APPS中。然后,在终端运行以下命令创建数据库迁移: ```shell python manage.py makemigrations python manage.py migrate ``` 接下来,你可以通过访问Django admin后台来添加定时任务。在后台中,你可以设置任务的名称、任务的类型(定时任务或周期性任务)、任务的执行时间等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值