0

我找到了一个文件锁定类的演示(这里: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 获取返回值。有人可以解释如何做到这一点吗?

4

2 回答 2

3

您应该使用以下内容:

@上下文管理器
def 文件锁(lock_file):
    而 os.path.exists(lock_file):
        print '一次只能运行一个脚本。'\
              '脚本被 %s 锁定' % lock_file
        时间.sleep(1)
    open(lock_file, 'w').write("1")
    尝试:
        屈服
    最后:
        os.remove(lock_file)

这直接满足了您声明的需求。OTOH该方法非常错误,因为在检查文件存在和打开文件之间存在明确的竞争条件。应该使用更稳定的方法O_EXCL来确保文件在创建期间不存在,或者flock对文件内容使用锁定,而不是对其存在。此外,可以使用一些内核级 IPC(Posix 信号量、SysV 信号量等)

于 2014-04-23T21:04:30.653 回答
0

我已经接受了 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")
于 2014-04-23T21:27:20.887 回答