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设计】的支持。

相关文章

使用k8s部署Django项目的方法步骤

接触了一下docker和k8s,感觉是非常不错的东西。能够方便的部署线上环境,而且还能够更好的利用机器的资源,感觉是以后的大趋势。最近刚好有一个基于django的项目,所以就把这个项目打...

python实现对指定输入的字符串逆序输出的6种方法

对于一个给定的字符串,逆序输出,这个任务对于python来说是一种很简单的操作,毕竟强大的列表和字符串处理的一些列函数足以应付这些问题 了,今天总结了一下python中对于字符串的逆序输...

Python实现将DOC文档转换为PDF的方法

本文实例讲述了Python实现将DOC文档转换为PDF的方法。分享给大家供大家参考。具体实现方法如下: import sys, os from win32com.client imp...

在Python中实现函数重载的示例代码

在Python中实现函数重载的示例代码

假设你有一个函数connect,它有一个参数address,这个参数可能是一个字符串,也可能是一个元组。例如: connect('123.45.32.18:8080') connec...

python负载均衡的简单实现方法

提到分发请求,相信大多数人首先会想到Nginx,Nginx作为一种多功能服务器,不仅提供了反向代理隐藏主机ip的能力,还拥有简单的缓存加速功能。当然Nginx最强大的功能还是分发请求,不...