我发现了一个文件锁定类的演示(此处:https://groups.google.com/forum/#!topic/pug pe/mQr7KX cenU),但我不太了解使用它的机制。
@contextmanager
def FileLock(lock_file):
if os.path.exists(lock_file):
print 'Only one script can run at once. '
'Script is locked with %s' % lock_file
sys.exit(-1)
else:
open(lock_file, 'w').write("1")
try:
yield
finally:
os.remove(lock_file)
我相信上面写着"如果传入的文件不存在,打开它。完成后,删除它。
演示的用途是:
with FileLock('/tmp/my_script.lock'):
print "I am here and I am sleeping for 10 sec..."
time.sleep(10)
它工作正常-如果我运行脚本一次,我看到"我在这里,我睡了10秒…",如果我在这10秒内再次运行,我会看到"一次只能运行一个脚本。脚本用/tmp/my_script.lock锁定"。然而,要使用文件锁,通常需要"等到获得锁"才能执行操作。然而,'sys.exit()'似乎阻止了这种情况的发生。似乎我想用某种方式将"with"包装在while循环中?类似于:
while fileIsLocked:
with FileLock('/tmp/my_script.lock'): # try to get the lock
print "I am here and I am sleeping for 10 sec..."
time.sleep(10)
但我不知道如何从FileLock中获取返回值。有人能解释一下怎么做吗?
您应该使用以下内容:
@上下文管理器def FileLock(lock_file):当os.path.存在时(lock_file):print'一次只能运行一个脚本。'\'脚本被%s锁定了'%lock_file时间睡眠(1)打开(lock_file,'w').write("1")尝试:产量最后:os.remove(锁定文件)
这直接满足了声明的需求。OTOH该方法非常有缺陷,因为在检查文件存在和打开文件之间存在明确的竞争条件。更稳定的方法应该使用O_EXCL
来确保文件在创建过程中不存在,或者使用flock
来锁定文件内容,而不是其存在。此外,还可以使用一些内核级IPC(Posix信号量、SysV信号量等)
我接受了Netch的回答,因为它既展示了我"声明"的需求的解决方案,又推荐了一个更好的解决方案。为了完整起见,我在这里发布了羊群的使用。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import fcntl
import time
try:
f = open('/tmp/locktest', 'w')
fcntl.flock(f, fcntl.LOCK_EX) # Get an exclusive lock - this will block until it gets the lock
print "Sleeping..."
time.sleep(10)
except IOError:
print("can't immediately write-lock the file ($!), blocking ...")
else:
print("No error")
print("End of file")