在 Python 中锁定文件

新手上路,请多包涵

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

原文由 Evan Fosmark 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 527
2 个回答

其他解决方案引用了大量外部代码库。如果您更愿意自己做,这里有一些跨平台解决方案的代码,它在 Linux / DOS 系统上使用各自的文件锁定工具。

 try:
    # Posix based file locking (Linux, Ubuntu, MacOS, etc.)
    #   Only allows locking on writable files, might cause
    #   strange results for reading.
    import fcntl, os
    def lock_file(f):
        if f.writable(): fcntl.lockf(f, fcntl.LOCK_EX)
    def unlock_file(f):
        if f.writable(): fcntl.lockf(f, fcntl.LOCK_UN)
except ModuleNotFoundError:
    # Windows file locking
    import msvcrt, os
    def file_size(f):
        return os.path.getsize( os.path.realpath(f.name) )
    def lock_file(f):
        msvcrt.locking(f.fileno(), msvcrt.LK_RLCK, file_size(f))
    def unlock_file(f):
        msvcrt.locking(f.fileno(), msvcrt.LK_UNLCK, file_size(f))

# Class for ensuring that all file operations are atomic, treat
# initialization like a standard call to 'open' that happens to be atomic.
# This file opener *must* be used in a "with" block.
class AtomicOpen:
    # Open the file with arguments provided by user. Then acquire
    # a lock on that file object (WARNING: Advisory locking).
    def __init__(self, path, *args, **kwargs):
        # Open the file and acquire a lock on the file before operating
        self.file = open(path,*args, **kwargs)
        # Lock the opened file
        lock_file(self.file)

    # Return the opened file object (knowing a lock has been obtained).
    def __enter__(self, *args, **kwargs): return self.file

    # Unlock the file and close the file object.
    def __exit__(self, exc_type=None, exc_value=None, traceback=None):
        # Flush to make sure all buffered contents are written to file.
        self.file.flush()
        os.fsync(self.file.fileno())
        # Release the lock on the file.
        unlock_file(self.file)
        self.file.close()
        # Handle exceptions that may have come up during execution, by
        # default any exceptions are raised to the user.
        if (exc_type != None): return False
        else:                  return True

现在, AtomicOpen 可以在 with 块中使用,其中通常使用 open 语句。

警告:

  • 如果在调用 exit 之前在 Windows 和 Python 上运行崩溃,我不确定锁定行为是什么。
  • 此处提供的锁定是建议性的,而不是绝对的。所有潜在的竞争进程都必须使用“AtomicOpen”类。
  • 截至(2020 年 11 月 9 日),此代码仅锁定 Posix 系统上的 可写 文件。在此日期发布之后的某个时候,在只读文件上使用 fcntl.lock 变得非法。

原文由 Thomas Lux 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏