我找到了一个文件锁定类的演示(这里: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获取返回值。有人可以解释一下如何做到这一点吗?
答案 0 :(得分:3)
您应该使用以下内容:
@contextmanager def FileLock(lock_file): while os.path.exists(lock_file): print 'Only one script can run at once. '\ 'Script is locked with %s' % lock_file time.sleep(1) open(lock_file, 'w').write("1") try: yield finally: os.remove(lock_file)
这直接回答了声明的需求。 OTOH方法非常错误,因为在检查文件存在和打开文件之间存在明确的竞争条件。更稳定的方法应该使用O_EXCL
来确保文件在创建期间不存在,或flock
使用锁定文件内容,而不是它的存在。此外,可以使用一些内核级IPC(Posix信号量,SysV信号量等)
答案 1 :(得分:0)
我已经接受了Netch的答案,因为它都证明了我声明的解决方案'需要,并建议更好的解决方案。我已经在这里发布了使用flock的完整性。
#!/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")