有没有简单的方法在Linux上使用Python系统范围的互斥锁?通过“系统范围”,我的意思是互斥体将由一组Python 进程使用;这与传统互斥体形成对比,传统互斥体在同一进程中由一组线程使用。
编辑:我不确定Python的multiprocessing
包是否是我需要的。例如,我可以在两个不同的解释器中执行以下操作:
from multiprocessing import Lock
L = Lock()
L.acquire()
当我在两个单独的解释器中同时执行这些命令时,我希望其中一个挂起。相反,它们都没有挂起;看起来他们没有获得相同的互斥锁。
答案 0 :(得分:28)
“传统的”Unix答案是使用文件锁。您可以使用lockf(3)
锁定文件的各个部分,以便其他进程无法编辑它;一个非常常见的滥用是将其用作进程之间的互斥。 python等价物是fcntl.lockf。
传统上,您将锁定进程的PID写入锁定文件,以便在保持锁定时因进程死亡而导致的死锁是可识别和可修复的。
这可以为您提供所需的内容,因为您的锁位于全局命名空间(文件系统)中,并且可供所有进程访问。这种方法还具有非Python程序可以参与锁定的特权。缺点是你需要一个这个锁文件存放的地方;此外,某些文件系统实际上并未正确锁定,因此存在无法实现排除的风险。你赢了一些,你输了一些。
答案 1 :(得分:12)
POSIX标准指定了可用于此目的的进程间信号量。 http://linux.die.net/man/7/sem_overview
Python中的multiprocessing
模块是基于此API和其他模块构建的。特别是,multiprocessing.Lock
提供了一个跨进程的“互斥”。 http://docs.python.org/library/multiprocessing.html#synchronization-between-processes
编辑以回复已修改的问题:
在您的概念证明中,每个过程都在构建Lock()
。所以你有两个单独的锁。这就是为什么这两个进程都没有等待您需要在进程之间共享相同的锁。我在multiprocessing
文档中链接的部分解释了如何执行此操作。
答案 2 :(得分:8)
试试ilock库:
from ilock import ILock
with ILock('Unique lock name'):
# The code should be run as a system-wide single instance
...
答案 3 :(得分:6)
我的答案与其他答案重叠,但只是为了增加人们可以复制粘贴的内容,我经常这样做。
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
,然后在两个或多个不同的终端(来自同一目录)中运行上述代码。
答案 4 :(得分:1)
对于系统范围的互斥锁,它允许同步完全独立的进程(即,不属于同一进程树的INCLUDE Linux进程),只需使用fcntl.flock即可。我想在Linux下使用内存文件' / run / shm文件夹可以使它执行得更快。
查看更多here。
答案 5 :(得分:0)
只需将一个添加到列表中,就可以使用posix_ipc库,该库具有一个Semaphore
类。
计数为1的信号量可用作 Mutex 。
为了完成线程三重奏,SystemEvent库使用了posix_ipc
并提供了 Event 。