Celery实现异步任务和定时任务的简单示例

Celery是python开发中广为使用的分布式任务队列框架,其整体框架如下图,包括消息中间件(Broker)、任务执行单元Worker、结果存储(Backend)三大部分。

在这里插入图片描述
本文仅举Celery在异步任务和定时任务的两个小示例。Backend采用redis-4.0.11, Celery版本为4.1.1。读者请注意不同版本redis和Celery的兼容性,同时注意不同版本Celery的API间的差异

一、异步任务

步骤一:在task.py文件中编写异步任务代码

from celery import Celery
import time

broker_url = "redis://127.0.0.1:6379/1"   # 使用redis存储任务队列
result_backend = "redis://127.0.0.1:6379/2"   # 使用redis存储结果

app = Celery("asyn_demo", broker=broker_url, backend=result_backend)     # 实例化 Celery对象
app.autodiscover_tasks('task01')

@app.task(name='task01')
def task01(string):
    """
    异步代码
    """
    time.sleep(10)
    with open('1.txt', 'a+', encoding='utf-8') as f:
        f.write("异步测试{}\n".format(string))

def task_run():
    task01.apply_async(args=["第一次尝试"])   # apply_async异步操作
    task01.apply_async(args=["第二次尝试"])

if __name__ == '__main__':
    task_run()

步骤二:终端cd到task.py文件所在目录,并启动worker

celery -A task.app worker --loglevel=info

其中,需要注意的参数的意义如下:
在这里插入图片描述
步骤三:启动task.py程序,即可观察到异步任务的执行。

二、定时任务

整个Celery定时任务脚本的文件层级架构(当然,异步任务也可以采用该架构)如下:
在这里插入图片描述
步骤一:配置celery文件,并编写定时任务
celery_config.py 配置文件

# -*- coding: utf-8 -*-
# @Time : 2019/11/29 下午1:56
# @Author : guofei
# @File : celery_config.py
from celery.schedules import crontab, timedelta

broker_url = "redis://127.0.0.1:6379/2"   # 使用redis存储任务队列
result_backend = "redis://127.0.0.1:6379/6"  # 使用redis存储结果
timezone = "Asia/Shanghai"   # 定义时区

imports = [
    "celery_task.epp_scripts.test1",  # 导入定时任务的py文件
    "celery_task.epp_scripts.test2",
]

# 需要执行任务的配置,通过beat__schedule来实现
beat_schedule = {
    "test1": {
        "task": "celery_task.epp_scripts.test1.celery_run",  #定时任务函数
        "schedule": timedelta(seconds=30),   # 调度时间
        "args": ()  # 任务函数参数,元组
    },

    "test2": {
        "task": "celery_task.epp_scripts.test2.celery_run",
        "schedule": timedelta(seconds=20),  
        "args": ()
    },

}

celery_main.py 主函数

from celery import Celery

# 创建celery应用对象
app = Celery("auto_handler")

# 导入celery的配置信息
app.config_from_object("celery_task.celery_config")

test1.py 定时任务1函数

from ..celery_main import app

def test11():
    print("test11----------------")

def test22():
    with open('task02.txt', 'a+', encoding='utf-8') as f:
        f.write('test22')
    test11()

@app.task
def celery_run():
    test11()
    test22()

if __name__ == '__main__':
    celery_run()

test2.py 定时任务2函数

from ..celery_main import app

def test33():
    print("test3----------------")

def test44():
    with open('task02.txt', 'a+', encoding='utf-8') as f:
        f.write('test44')
    test33()

@app.task
def celery_run():
    test33()
    test44()

if __name__ == '__main__':
    celery_run()

步骤二: 终端cd到celery_task文件所在目录,并启动定时服务

celery -A celery_task.celery_main beat

步骤三: 终端cd到celery_task文件所在目录,并启动worker

celery -A celery_task.celery_main worker --loglevel=info

此时,就可以看到相关后台定时任务的执行。步骤二和步骤三可以合并到如下一条命令:

celery -B -A celery_task.celery_main worker --loglevel=info

三、其它事项

3.1 定时任务crontab

频率性的任务可以用timedelta函数进行时间间隔空值。若想在每天的每个固定时间点进行定时任务,则需要改用crontab,如:

"schedule": crontab(hour=18, minute=0)    # 每天晚6点

此时,要特别注意celery_config.py 配置文件中需配置好时区timezone

3.2 Celery-4.1.1版本中的bug

在该版本的Celery中,由于在读取实时时间now时的bug,无法对crontab做出正确的定时任务启动。此时,需要对celery_main.py 主函数中Celery对象进行如下修改:

class MyCelery(Celery):
    def now(self):
        """Return the current time and date as a datetime."""
        from datetime import datetime
        return datetime.now(self.timezone)


app = MyCelery("my_handler")
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值