python 跨平台文件锁

603 阅读1分钟
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @file    : FileLocker.py
# @detail  : 掘金首发测试
# @Date    : 2020/9/10 09:48
# @Author  : Cina Luser (king-afu@hotmail.com)
# @Link    : https://github.com/xiaoqiong0v0
# @Version : 1.0.0
import time
import platform

# 动态载入模块
fcntl = None
msvcrt = None
bLinux = True
if platform.system() != 'Windows':
    fcntl = __import__("fcntl")
    bLinux = True
else:
    msvcrt = __import__('msvcrt')
    bLinux = False

class LockTimeOutError(Exception):
    pass

class UnLockTimeOutError(Exception):
    pass

# 文件锁
class FileLocker:
    def __init__(self, filename=None):
        if filename:
            self.filename = filename + '.lock'
        else:
            self.filename = None
        self.file = None

    # 文件加锁
    def lock(self, filename=None):
        if filename:
            self.filename = filename
        self.file = open(self.filename, 'wb')
        if bLinux is True:
            try:
                fcntl.flock(self.file, fcntl.LOCK_EX | fcntl.LOCK_NB)
            except:
                return False
        else:
            try:
                msvcrt.locking(self.file.fileno(), msvcrt.LK_NBLCK, 1)
            except:
                return False
            return True
    # 文件解锁
    def unlock(self, filename=None):
        if filename:
            self.filename = filename
            self.file = open(self.filename, 'wb')
        try:
            if bLinux is True:
                fcntl.flock(self.file, fcntl.LOCK_UN)
                self.file.close()
            else:
                self.file.seek(0)
                msvcrt.locking(self.file.fileno(), msvcrt.LK_UNLCK, 1)
            return True
        except:
            return False
    # 等待式文件加锁
    def force_lock(self, time_out=None, filename=None):
        while not self.lock(filename):
            time.sleep(0.1)
            if time_out is not None:
                time_out -= 0.1
                if time_out <= 0:
                    raise LockTimeOutError
    # 等待式文件解锁
    def force_unlock(self, time_out=None, filename=None):
        while not self.unlock(filename):
            time.sleep(0.1)
            if time_out is not None:
                time_out -= 0.1
                if time_out <= 0:
                    raise UnLockTimeOutError