【问题标题】:Is python's shutil.copyfile() atomic?python 的 shutil.copyfile() 是原子的吗?
【发布时间】:2023-04-17 22:55:01
【问题描述】:

我正在编写一个 python 脚本,它在 Linux 上使用 shutil.copyfile() 复制文件。在复制期间,其他进程可能正在尝试读取该文件。以下是否足以确保外部进程不会获得文件的损坏视图?

os.unlink(dest)
shutil.copyfile(src, dest)

也就是说,shutil.copyfile() 是原子的,以至于其他进程在复制操作完成之前无法读取目标文件?

【问题讨论】:

  • 最好复制到同目录下的一个临时文件,然后os.rename()。 *ix:这种方式是原子的,即使在 NFS 上也是如此。如果一个或多个进程已经打开了文件,它们将继续看到旧版本,而文件的后续 open() 将看到新内容。

标签: python linux shutil


【解决方案1】:

不,shutil.copyfile 不是原子的。这是definition of shutil.copyfile:的一部分

def copyfile(src, dst, *, follow_symlinks=True):    
    ...
    with open(src, 'rb') as fsrc:
        with open(dst, 'wb') as fdst:
            copyfileobj(fsrc, fdst)

copyfileobj is defined like this:

def copyfileobj(fsrc, fdst, length=16*1024):
    while 1:
        buf = fsrc.read(length)
        if not buf:
            break
        fdst.write(buf)

调用copyfile 的线程可以在这个while-loop 中停止,此时其他进程可能会尝试打开要读取的文件。它会得到一个损坏的文件视图。

【讨论】:

    【解决方案2】:

    不,似乎只是loop, reading and writing 16KB at a time

    对于原子复制操作,您应该将文件复制到同一文件系统上的不同位置,然后将os.rename() 复制到所需位置( 保证在 Linux 上是原子的) .

    【讨论】:

      最近更新 更多