filelock , 一個(gè)神奇的 Python 庫(kù)
filelock 是一個(gè) Python 第三方庫(kù),用于實(shí)現(xiàn)跨平臺(tái)的文件鎖功能。它允許多個(gè)線程或進(jìn)程在訪問(wèn)共享文件時(shí)進(jìn)行互斥操作,避免并發(fā)寫入等問(wèn)題導(dǎo)致的數(shù)據(jù)混亂。

安裝
pip install filelock特性
- 支持基于文件的鎖定機(jī)制
- 提供了上下文管理器來(lái)自動(dòng)管理鎖的獲取和釋放
- 支持超時(shí)機(jī)制,防止死鎖情況發(fā)生
- 可以管理多個(gè)文件的鎖定狀態(tài)
基礎(chǔ)示例
from filelock import FileLock
# 定義鎖文件(通常是在目標(biāo)文件后加.lock)和數(shù)據(jù)文件
lock_file = "data.txt.lock"
data_file = "data.txt"
# 創(chuàng)建一個(gè)鎖對(duì)象
lock = FileLock(lock_file)
# 使用with語(yǔ)句獲取鎖(阻塞直到獲取鎖)
with lock:
with open(data_file, "a") as f:
f.write("新條目\n")
# 鎖會(huì)在with塊結(jié)束后自動(dòng)釋放data.txt.lock 是鎖文件的名稱。當(dāng)獲取文件鎖時(shí),會(huì)創(chuàng)建這個(gè)文件,釋放鎖時(shí),會(huì)刪除這個(gè)文件(如果文件系統(tǒng)支持刪除操作,否則可能只是釋放鎖,文件仍然存在)。
(1) 非阻塞鎖
通過(guò)設(shè)置鎖的timeout超時(shí)時(shí)間為0,設(shè)置為非阻塞鎖
try:
# 設(shè)置timeout=0表示非阻塞,如果獲取不到鎖立即拋出Timeout異常
with lock.acquire(timeout=0):
with open(data_file, "a") as f:
f.write("快速更新\n")
except Timeout:
print("鎖被占用,稍后再試。")(2) 手動(dòng)控制鎖
lock.acquire() # 獲取鎖(阻塞)
try:
with open(data_file, "a") as f:
f.write("手動(dòng)加鎖\n")
finally:
lock.release() # 務(wù)必在finally中釋放鎖,避免死鎖實(shí)際應(yīng)用
(1) 數(shù)據(jù)庫(kù)連接池中的文件鎖定
在數(shù)據(jù)庫(kù)連接池的實(shí)現(xiàn)中,通常會(huì)使用文件鎖來(lái)控制對(duì)數(shù)據(jù)庫(kù)連接文件的并發(fā)訪問(wèn)。
from filelock import FileLock
# 創(chuàng)建數(shù)據(jù)庫(kù)連接池文件鎖
db_lock = FileLock("db_pool.lock")
# 獲取數(shù)據(jù)庫(kù)連接
def get_db_connection():
with db_lock:
# 在鎖定范圍內(nèi)執(zhí)行獲取數(shù)據(jù)庫(kù)連接的操作
print("獲取數(shù)據(jù)庫(kù)連接")
# 返回?cái)?shù)據(jù)庫(kù)連接對(duì)象
return db_connection使用文件鎖 db_lock 來(lái)控制對(duì)數(shù)據(jù)庫(kù)連接池文件的并發(fā)訪問(wèn),確保同一時(shí)間只有一個(gè)線程可以獲取數(shù)據(jù)庫(kù)連接。
(2) 多線程/多進(jìn)程環(huán)境下的文件訪問(wèn)控制
在多線程或多進(jìn)程的環(huán)境中,文件鎖可以用來(lái)控制對(duì)共享文件的并發(fā)訪問(wèn),避免數(shù)據(jù)競(jìng)爭(zhēng)和沖突。
from filelock import FileLock
from concurrent.futures import ThreadPoolExecutor
# 創(chuàng)建文件鎖
file_lock = FileLock("shared_file.txt.lock")
# 多線程處理文件寫入操作
def write_to_file(data):
with file_lock:
# 在鎖定范圍內(nèi)執(zhí)行文件寫入操作
with open("shared_file.txt", "a") as file:
file.write(data + "\n")
# 創(chuàng)建線程池
executor = ThreadPoolExecutor(max_workers=5)
# 提交多個(gè)寫入任務(wù)
data_list = ["Data 1", "Data 2", "Data 3", "Data 4", "Data 5"]
for data in data_list:
executor.submit(write_to_file, data)使用文件鎖file_lock來(lái)控制多線程環(huán)境下對(duì)共享文件的并發(fā)寫入操作,確保數(shù)據(jù)寫入的安全性和一致性。
(3) 日志文件的并發(fā)寫入控制
在日志系統(tǒng)中,多個(gè)進(jìn)程或線程同時(shí)寫入日志文件時(shí),可以使用文件鎖來(lái)控制對(duì)日志文件的并發(fā)訪問(wèn),避免日志信息錯(cuò)亂和丟失
from filelock import FileLock
import logging
# 創(chuàng)建日志文件鎖
log_lock = FileLock("app.log.lock")
# 配置日志系統(tǒng)
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# 寫入日志信息的函數(shù)
def write_log_message(message):
with log_lock:
# 在鎖定范圍內(nèi)執(zhí)行寫入日志信息的操作
logging.info(message)
# 測(cè)試寫入日志信息
write_log_message("This is a log message.")使用文件鎖log_lock來(lái)控制對(duì)日志文件的并發(fā)寫入操作,確保日志信息按照正確的順序?qū)懭胛募小?/p>
注意事項(xiàng)
- 文件鎖并不是 100% 安全的。在某些極端情況下,如系統(tǒng)崩潰等,可能會(huì)導(dǎo)致文件鎖狀態(tài)不一致。
- 不同操作系統(tǒng)對(duì)文件鎖的支持方式可能有所不同。filelock 庫(kù)盡量屏蔽了這些差異,但在使用時(shí)還是需要注意潛在的兼容性問(wèn)題。
- 對(duì)于頻繁的文件讀寫操作,文件鎖可能會(huì)帶來(lái)一定的性能開(kāi)銷,因?yàn)樾枰粩嗟孬@取和釋放鎖。在這種情況下,可以考慮優(yōu)化文件操作邏輯,盡量減少鎖的使用頻率。



































