我需要锁定一个文件写在Python。它将被多个Python进程同时访问。我在网上找到了一些解决方案,但大多数都无法达到我的目的,因为它们通常只是基于Unix或Windows的。


当前回答

这里有一个跨平台的文件锁定模块:Portalocker

尽管正如Kevin所说,从多个进程同时写入文件是您希望尽可能避免的事情。

如果可以将问题硬塞到数据库中,则可以使用SQLite。它支持并发访问并处理自己的锁定。

其他回答

锁定是平台和设备特定的,但一般来说,你有几个选择:

Use flock(), or equivalent (if your os supports it). This is advisory locking, unless you check for the lock, it's ignored. Use a lock-copy-move-unlock methodology, where you copy the file, write the new data, then move it (move, not copy - move is an atomic operation in Linux -- check your OS), and you check for the existence of the lock file. Use a directory as a "lock". This is necessary if you're writing to NFS, since NFS doesn't support flock(). There's also the possibility of using shared memory between the processes, but I've never tried that; it's very OS-specific.

对于所有这些方法,您必须使用自旋锁(失败后重试)技术来获取和测试锁。这确实为错误同步留下了一个小窗口,但它通常小到不会成为一个大问题。

如果您正在寻找跨平台的解决方案,那么您最好通过其他机制将日志记录到另一个系统(其次是上面的NFS技术)。

请注意,sqlite在NFS上受到与普通文件相同的约束,因此您不能在网络共享上写入sqlite数据库并免费获得同步。

这招对我很管用: 不占用大文件,分布在几个小文件中 创建文件Temp,删除文件A,然后将文件Temp重命名为A。

import os
import json

def Server():
    i = 0
    while i == 0:
        try:        
                with open(File_Temp, "w") as file:
                    json.dump(DATA, file, indent=2)
                if os.path.exists(File_A):
                    os.remove(File_A)
                os.rename(File_Temp, File_A)
                i = 1
        except OSError as e:
                print ("file locked: " ,str(e))
                time.sleep(1)
            
            
def Clients():
    i = 0
    while i == 0:
        try:
            if os.path.exists(File_A):
                with open(File_A,"r") as file:
                    DATA_Temp = file.read()
            DATA = json.loads(DATA_Temp)
            i = 1
        except OSError as e:
            print (str(e))
            time.sleep(1)

锁定文件通常是特定于平台的操作,因此您可能需要考虑在不同的操作系统上运行的可能性。例如:

import os

def my_lock(f):
    if os.name == "posix":
        # Unix or OS X specific locking here
    elif os.name == "nt":
        # Windows specific locking here
    else:
        print "Unknown operating system, lock unavailable"

我从grizzed -python中找到了一个简单而有效的(!)实现。

简单使用os.open(…, O_EXCL) + os.close()在windows上不起作用。

你会发现pylocker很有用。它可以用于锁定文件或一般的锁定机制,并且可以从多个Python进程一次访问。

如果你只是想锁定一个文件,下面是它的工作原理:

import uuid
from pylocker import Locker

#  create a unique lock pass. This can be any string.
lpass = str(uuid.uuid1())

# create locker instance.
FL = Locker(filePath='myfile.txt', lockPass=lpass, mode='w')

# aquire the lock
with FL as r:
    # get the result
    acquired, code, fd  = r

    # check if aquired.
    if fd is not None:
        print fd
        fd.write("I have succesfuly aquired the lock !")

# no need to release anything or to close the file descriptor, 
# with statement takes care of that. let's print fd and verify that.
print fd