我的回答与其他回答有重叠之处,但为了添加一些人们可以复制粘贴的内容,我经常做这样的事情。
class Locker:
def __enter__ (self):
self.fp = open("./lockfile.lck")
fcntl.flock(self.fp.fileno(), fcntl.LOCK_EX)
def __exit__ (self, _type, value, tb):
fcntl.flock(self.fp.fileno(), fcntl.LOCK_UN)
self.fp.close()
然后将其用作:
print("waiting for lock")
with Locker():
print("obtained lock")
time.sleep(5.0)
要进行测试,执行 touch lockfile.lck
,然后在两个或多个不同的终端中运行上面的代码(从相同的目录中运行)。
更新:smwikipedia提到我的解决方案是Unix特定的。最近我需要一个便携式版本,并从一个随机的github项目中提出了以下想法。我不确定是否需要seek()调用,但它们存在是因为Windows API锁定文件中的特定位置。如果您除了锁定之外不使用该文件,则可能可以删除这些seeks。
if os.name == "nt":
import msvcrt
def portable_lock(fp):
fp.seek(0)
msvcrt.locking(fp.fileno(), msvcrt.LK_LOCK, 1)
def portable_unlock(fp):
fp.seek(0)
msvcrt.locking(fp.fileno(), msvcrt.LK_UNLCK, 1)
else:
import fcntl
def portable_lock(fp):
fcntl.flock(fp.fileno(), fcntl.LOCK_EX)
def portable_unlock(fp):
fcntl.flock(fp.fileno(), fcntl.LOCK_UN)
class Locker:
def __enter__(self):
self.fp = open("./lockfile.lck")
portable_lock(self.fp)
def __exit__(self, _type, value, tb):
portable_unlock(self.fp)
self.fp.close()