前言
GPU.dat的内容如下
81e443bd-b826-4459-999d-685fa63e8a88:/dev/dri/renderD128
166a4eab-fc0d-4264-a35d-8b78e09f22ea:/dev/dri/renderD128
56e846d8-b422-4720-b3e5-c2813b756b9b:/dev/dri/renderD128
2b1a1ecb-357f-4adc-9639-97bf6c8a8e9f:/dev/dri/renderD128
0492e933-0e1f-44c0-b2f3-80f4966bb8ae:/dev/dri/renderD128
b8f4710f-efc1-471b-9055-34fe7261d98b:/dev/dri/renderD128
6214c986-3ba2-420a-a3db-5a1411841de1:/dev/dri/renderD128
c960ee33-f8c2-4255-bbe9-1e971cf4065b:/dev/dri/renderD128
8bb6c888-1f03-4898-b396-4f57ca1571c9:/dev/dri/renderD128
d7afdf91-5ae8-41b9-9610-4a1a73fa3560:/dev/dri/renderD128
55a5a399-aed5-49d3-8fb4-bd16816ba3b2:/dev/dri/renderD128
576bce10-d36a-4a4c-9202-e2a55aa29b89:/dev/dri/renderD128
想要删除指定uuid的某一行,以及多进程调用这个读写文件时怎么实现。
删除某一行
import os
dir = 'test'
gpu_file = os.path.join(dir, 'GPU.dat')
if os.path.exists(gpu_file):
lines = [l for l in open(gpu_file, "r") if l.find('c960ee33-f8c2-4255-bbe9-1e971cf4065b', 0, 36) != 0]
fd = open(gpu_file, "w")
fd.writelines(lines)
fd.close()
文件锁介绍
GPU.dat相当于一个数据库,添加删除都要做记录,但是当多进程调用时,如一个正打开文件做添加数据操作,另一个进程却要打开文件做删除数据记录,必然会造成文件记录的数据混乱,虽然多进程可以用加锁来解决竞争调用,但是这是从运行的程序来说,而文件锁则要简单的多。
标志位 | 含义 |
LOCK_SH | 表示要创建一个共享锁,所有进程没有写访问权限,即使是加锁进程也没有。所有进程有读访问权限,在任意时间内,一个文件的共享锁可以被多个进程拥有。 |
LOCK_EX | 表示创建一个排他锁,在任意时间内,一个文件的排他锁只能被一个进程拥有 |
LOCK_UN | 表示删除该进程创建的锁 |
LOCK_NB | 如果指定此参数,函数不能获得文件锁就立即返回,否则,函数会等待获得文件锁。LOCK_NB可以同LOCK_SH或LOCK_NB进行按位或(|)运算操作。 fcnt.flock(f,fcntl.LOCK_EX|fcntl.LOCK_NB) |
通常情况下,如果加锁请求不能被立即满足,那么系统调用 flock()会阻塞当前进程。比如,进程想要请求一个排他锁,但此时,已经由其他进程获取了这个锁,那么该进程将会被阻塞。
注意:
- 对于文件的 close() 操作会使文件锁失效;
- 同理,进程结束后文件锁失效;
- flock() 的 LOCK_EX是“劝告锁”,系统内核不会强制检查锁的状态,需要在代码中进行文件操作的地方显式检查才能生效。
import fcntl
import os
dir = 'test'
gpu_file = os.path.join(dir, 'GPU.dat')
if os.path.exists(gpu_file):
lines = [l for l in open(gpu_file, "r") if l.find('c960ee33-f8c2-4255-bbe9-1e971cf4065b', 0, 36) != 0]
fd = open(gpu_file, "w")
fcntl.flock(fd, fcntl.LOCK_EX)
fd.writelines(lines)
fcntl.flock(fd, fcntl.LOCK_EX)
fd.close()
示例
import fcntl
import os
import sys
import threading
import time
dir = 'test'
def writing(name):
"""写操作"""
gpu_file = os.path.join(dir, 'test.dat')
if not os.path.exists(gpu_file):
os.mknod(gpu_file)
with open(gpu_file, 'a') as f:
fcntl.flock(f, fcntl.LOCK_EX) #对文件进行加锁
f.write(name + '\n')
fcntl.flock(f, fcntl.LOCK_UN) #对文件进行解锁
def deleting(name):
"""删操作"""
gpu_file = os.path.join(dir, 'test.dat')
if os.path.exists(gpu_file):
lines = [l for l in open(gpu_file, "r") if l.find(name, 0, 1) != 0]
print('lines=%s'%lines)
fd = open(gpu_file, "w")
fcntl.flock(fd, fcntl.LOCK_EX)
fd.writelines(lines)
fcntl.flock(fd, fcntl.LOCK_UN)
fd.close()
else:
print('文件不存在呢,拜拜了您!')
sys.exit(1)
if __name__ == '__main__':
p_d = multiprocessing.Pool(20)
p_w = multiprocessing.Pool(20)
a = [chr(i) for i in range(65,91)] #26个大写字母
for i in a:
threading.Thread(target=writing, kwargs={'name':i}).start()
a.remove(a[-1])
for j in a:
p_d.apply_async(deleting, j)
i = '@@' + j
p_w.apply_async(writing,(i,))
p_w.close()
p_w.join()
运行后的结果
Z
@@A
@@U
@@V
@@W
@@X
@@Y
@@B
@@C
@@D
@@E
@@F
@@G
@@H
@@I
@@J
@@K
@@L
@@M
@@N
@@O
@@P
@@Q
@@R
@@S
@@T
如果不加文件锁,文件记录结果可能会发生混乱。
查看官方文档说明可以知道,python中的fcntl是对Unix的fcntl进行封装,并且可以细节到对文件的一部分进行加锁,这部分可以参考python的fcntl官方文档说明。
后言
os.path.exists(gpu_file)
os.path.join(dir, 'test.dat')