Django如何防止定时任务并发浅析

yipeiwu_com7年前Python基础

前言

django提供了commands类,允许我们编写命令行脚本,并且可以通过python manage.py拉起。

了解commands

具体django commands如何使用,大家参考官方文档即可:https://docs.djangoproject.com/en/2.2/howto/custom-management-commands/

一个坑

使用时遇到一个坑:在commands运行中的异常并不会打印到屏幕上,它要求我们必须抛出CommandError类型的异常才能被打印到屏幕中,具体参考:https://docs.djangoproject.com/en/2.2/howto/custom-management-commands/#command-exceptions

文件锁防并发

我们通常利用Crontab拉起定时任务,那么就会面临一个常见问题,如何避免前一次没结束而后一次再次启动的问题。

通常都是用文件锁来搞定这个事情,我做了一个简单的装饰器来包装Commands的handle方法,定义一套元类或者类装饰器都可以达到同样的目的,这里就不炫技了。

# -*- coding: utf-8 -*-
import fcntl
import os
from apps.settings import CRON_LOCK_DIR


# 尝试加锁
def try_lock(name):
  def decorator(func):
    def wrap(*args, **kwargs):
      os.makedirs(CRON_LOCK_DIR, exist_ok=True)
      with open('{}/{}'.format(CRON_LOCK_DIR, name), 'w') as fd:
        try:
          fcntl.lockf(fd, fcntl.LOCK_EX | fcntl.LOCK_NB) # 加锁
          func(*args, **kwargs)
          fcntl.lockf(fd, fcntl.LOCK_UN) # 解锁
        except: # 加锁异常跳过
          pass
    return wrap
  return decorator

其中CRON_LOCK_DIR是文件锁的父目录,下面放了若干锁文件。

对Commands的handle方法指定锁文件名即可:

class Command(BaseCommand):
  @try_lock('check_order') # 指定锁文件的名字
  def handle(self, *args, **options):
    pass

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对【听图阁-专注于Python设计】的支持。

相关文章

在Docker上开始部署Python应用的教程

在Docker上开始部署Python应用的教程

几周前, Elastic Beanstalk声明在AWS云中配置和管理Docker容器。在本文中,我们通过一个简单的注册表单页面应用去理解Docker部署过程,该表单使用Elastic...

Python字符串中添加、插入特定字符的方法

Python字符串中添加、插入特定字符的方法

分析 我们将添加、插入、删除定义为: 添加 : 在字符串的后面或者前面添加字符或者字符串 插入 : 在字符串之间插入特定字符 在Python中,字符串是不可变的。所以无法直接删除、插入...

用Python实现最速下降法求极值的方法

用Python实现最速下降法求极值的方法

对于一个多元函数,用最速下降法(又称梯度下降法)求其极小值的迭代格式为 其中为负梯度方向,即最速下降方向,αkαk为搜索步长。 一般情况下,最优步长αkαk的确定要用到线性搜索技术,比...

朴素贝叶斯Python实例及解析

本文实例为大家分享了Python朴素贝叶斯实例代码,供大家参考,具体内容如下 #-*- coding: utf-8 -*- #添加中文注释 from numpy import *...

Flask模板引擎之Jinja2语法介绍

Jinja是组成Flask的模板引擎。可能你还不太了解它是干嘛的,但你对下面这些百分号和大括号肯定不陌生: {% block body %} <ul> {% for...