多个进程共享同一份资源共享内存文件等)时,会涉及到资源竞争问题。为了解决这种问题,一般采取的措施是进程在访问资源加锁保护,避免多个进程同时读写本文介绍的Python文件可以用来解决多进程的同步问题


1 Linux下的Python文件

Linux使用文件用到fcntl模块,该模块标准库,用来文件描述符执行文件控制和I/O控制
fcntl的文件用到fcntl.flock(fd, operation)方法,它的官方说明如下

文件描述符fd执行锁定操作
如果flock()失败,将引发OSError异常

参数含义:
fd:要锁定的文件的描述符
operation操作类型,有以下三种

类型 描述
LOCK_UN 解锁
LOCK_SH 获取共享锁,所有进程都只能读,不能写
LOCK_EX 获取独占锁,只有当前进程可以读写
LOCK_NB 阻塞加锁失败成功都立即返回,如果不加这个参数函数会一直阻塞,直到拿到锁。

用法

def tryLock(f) :
    try :
        fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
        return True
    except Exception as e:
        return False

def tryUnLock(f) :
    try :
        fcntl.flock(f, fcntl.LOCK_UN)
        return True
    except Exception as e:
        return False

f = open('file.txt', 'w+')
if tryLock(f) == True:
    f.write('1234')
    tryUnLock(f)

flock函数执行失败时,会抛出异常,所以要用tryexcept捕捉,避免flock时候程序退出
fcntl模块支持独占模式下写文件。

2 Windows下的Python文件锁

Windows版本的Python没有提供fcntl模块,它使用文件锁时使用的是filelock模块需要自己安装
打开命令行安装

pip install filelock

虽然没找到filelock官方文档,但可以通过dir函数来看它有些什么方法

import filelock 
print(dir(filelock))

输出

['AcquireReturnProxy', 'BaseFileLock', 'FileLock', 'SoftFileLock', 
'Timeout', 'UnixFileLock', 'WindowsFileLock', '_FileLock', '__all__', 
'__annotations__', '__builtins__', '__cached__', '__doc__', '__file__',
'__loader__', '__name__', '__package__', '__path__', '__spec__',
'__version__', '_api', '_error', '_soft', '_unix', '_util', '_windows',
'annotations', 'has_fcntl', 'sys', 'version', 'warnings']

Python里形如__xxx__的一般都是私有成员

没有直接提供方法,但从中能看到一个FileLock类和__path__路径打印一下。

import filelock 
print(dir(filelock.FileLock))
print(filelock.__path__)

输出

['__abstractmethods__', '__call__', '__class__', '__del__', 
'__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', 
'__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', 
'__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', 
'__lt__', '__module__', '__ne__', '__new__', '__reduce__', 
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', 
'__str__', '__subclasshook__', '__weakref__', '_abc_impl', '_acquire', 
'_recreate_cm', '_release', 'acquire', 'is_locked', 'lock_file', 'release', 'timeout']

['D:\xxx\xxx\xxx\site-packages\filelock']

FileLock提供了acquire、is_lockedreleasetimeout。按照名称acquire和release是上锁和解锁方法timeout是上锁的超时限制
进入__path__所在目录,用vscode全局搜索分别找到FileLock、acquire、releasetimeout
在这里插入图片描述
用这种方法得到以下使用例程

from filelock import FileLock
import time

def tryLock(locker, timeout = 3):
    try:
        locker.acquire(timeout)
        return True
    except Exception as e:
        return False

def tryUnLock(locker):
    try:
        locker.release()
        return True
    except Exception as e:
        return False

locker = FileLock('file.txt')
if tryLock(locker, 0.1) == True:
    time.sleep(5)
    tryUnLock(locker)

filelock同样是通过抛出异常表示上锁失败
filelock模块在上锁状态下不允许写文件。
filelock支持在Linux环境使用

3 总结

在Linux环境下可以用fcntl或者filelock模块来实现文件锁功能,而在Windows环境下只能用filelock。
fcntl和filelock上锁的区别

filelock fcntl
可以设置阻塞超时时长 可以设置阻塞和非阻塞没有超时机制
上锁后不能访问文件 在LOCK_EX 独占模式下,当前进程可以读写文件
需要自行安装 Python自带标准

3.1 filelock的使用场景

filelock在上锁之后不能访问文件,那么它有什么用呢?
应用中可以把filelock上锁的文件作为进程间同步的标志物,比如以下例子
tryLock和tryUnLock使用的是第二节例程的。

进程一

locker = FileLock('lock_file')
while True:
    if tryLock(locker) == True:
		## operate1
		tryUnLock(locker)

进程二

locker = FileLock('lock_file')
while True:
    if tryLock(locker) == True:
		## operate2
		tryUnLock(locker)

以上两个进程同时运行,可以确保操作互不干扰。

原文地址:https://blog.csdn.net/weixin_45001971/article/details/129009768

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_47812.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注