使用 `with:` 语句的 Python 文件锁模块行为
Posted
技术标签:
【中文标题】使用 `with:` 语句的 Python 文件锁模块行为【英文标题】:Python filelock module behavior using `with:` statement 【发布时间】:2017-06-15 04:56:23 【问题描述】:我只是想知道 python 模块文件锁的细节及其在某些情况下的行为。
首先,线程如何处理with:
语句。如果多个线程调用with:
,它是逐个线程锁定的吗?是否也有可能两个线程同时获取锁?
其次,当我使用with:
时,我必须在使用后清除锁定吗? with:
语句执行完后锁会自动清零吗?
第三,我的代码中有一个实例,我认为必须创建一个文件然后立即锁定。目前我正在使用这个:
channel_file = open(os.path.join('channels', username), 'w+')
with filelock.FileLock(os.path.join('channels', username)):
channel_file.write(json.dumps('rate': reobj.group(1),'time': reobj.group(2)))
如果有可能另一个线程从文件创建时就可以读取该文件,这是否可以防止这种情况发生?
这也带来了第四点。使用with:
时文件锁是否会锁定读取访问权限?
【问题讨论】:
【参考方案1】:FileLock 维护一个锁计数器,该计数器在进程中的所有线程之间共享,并受到线程锁的保护。每次调用acquire()
都会增加锁计数器,并在计数器为零时额外获得操作系统级别的文件锁。同样,每次调用release()
都会减少锁定计数器并在计数器达到零时解锁文件。
因此,如果两个线程同时获得锁,则该文件将在操作系统级别被该进程锁一次,锁计数器将增加2。两个线程不会互相阻塞。
with:
的重点是在其作用域退出后自动获取和释放锁。见What is the python "with" statement designed for?。
文件锁用于防止当前进程之外的文件访问。它不用于线程锁定。使用常规的threading.Lock
进行线程锁定。
# in __main__ or somewhere before we start the threads.
channel_lock = threading.Lock()
# in the worker thread
with channel_lock:
with open(...) as channel_file:
channel_file.write(...)
实现细节可以参考source code of py-filelock
。
【讨论】:
以上是关于使用 `with:` 语句的 Python 文件锁模块行为的主要内容,如果未能解决你的问题,请参考以下文章