python装饰器执行顺序_一个有用的python装饰器 -- 为执行程序加锁

最近在写python项目的时候遇到一个问题

有这样一个python脚本:

1 脚本功能

A 监控网卡的实时流量,如果该流量超过设定阀值就去增加带宽(购买带宽包)

B 脚本放在 crontab 中,并且是每分钟执行一次

2 遇到问题

在执行脚本的过程中,如果一分钟内该程序没有执行完,就可能会有两个相同的代码同时执行,导致的问题是 会同时购买两次带宽包,这样会造成资源的浪费。

3 解决思路

A 可以调整crontab,增加代码执行的时间(治标不治本)

B 为该程序加锁,同一时间只允许运行一个监控程序。

4 解决步骤

因此,怎么为程序加锁,还要尽量减少对源代码的更改,是问题的关键,我这里使用到了python的装饰器。

思路是这样的:

A 打开一个 xx.pid 文件,并为这个文件加上锁

B 获取当前执行程序的PID,并写入到 xx.pid文件中

C 执行程序,执行结束后关闭并且删除该xx.pid文件

5 上代码#!/usr/bin/python

# -*- coding: utf-8 -*-

import fcntl

from functools import wraps

import os

def singleton(pid_filename):

def decorator(f):

@wraps(f)

def decorated(*args, **kwargs):

pid = str(os.getpid())

pidfile = open(pid_filename, 'a+')

try:

#创建一个排他锁,并且所被锁住其他进程不会阻塞

fcntl.flock(pidfile.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)

except IOError:

return

pidfile.seek(0)

pidfile.truncate() # 清空文件

pidfile.write(pid)

pidfile.flush()

pidfile.seek(0)

ret = f(*args, **kwargs)

try:

pidfile.close()

except IOError, err:

# 可能的错误 IOError: [Errno 9] Bad file descriptor

if err.errno != 9:

return

os.remove(pid_filename)

return ret

return decorated

return decorator

注意:

fcntl 仅在 linux系统中使用,在windows中无效

6 简单用例@singleton('/tmp/add_bandwidth.pid')

def add_bandwidth():

pass

7 代码解析

这里使用到了python 的fcntl模块 -- python中给文件加锁

简单示例:>>> import fcntl

>>> f = open('test.txt')

>>> fcntl.flock(f.fileno(),fcntl.LOCK_EX) #对文件加锁

>>> fcntl.flock(f.fileno(),fcntl.LOCK_UN) #对文件解锁

----------------------

fcntl模块 中的flock(fd, operation):

参数 fd 表示文件描述符;

参数 operation 指定要进行的锁操作,该参数的取值有如下几种:

operation : 包括: fcntl.LOCK_UN 解锁 fcntl.LOCK_EX 排他锁 fcntl.LOCK_SH 共享锁 fcntl.LOCK_NB 非阻塞锁 LOCK_SH 共享锁:所有进程没有写访问权限,即使是加锁进程也没有。所有进程有读访问权限。 LOCK_EX 排他锁:除加锁进程外其他进程没有对已加锁文件读写访问权限。 LOCK_NB 非阻塞锁:如果指定此参数,函数不能获得文件锁就立即返回,否则,函数会等待获得文件锁。

LOCK_NB可以同LOCK_SH或LOCK_NB进行按位或(|)运算操作。 fcnt.flock(f,fcntl.LOCK_EX|fcntl.LOCK_NB)

注意:1. 对于文件的 close() 操作会使文件锁失效;

2. 同理,进程结束后文件锁失效;

3. flock() 的 LOCK_EX是“劝告锁”,系统内核不会强制检查锁的状态,需要在代码中进行文件操作的地方显式检查才能生效。

详情请查看官方文档:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值