Python 3 的 pathlib 中的 Path.write_text 方法是否具有原子性?

3

我在想,pathlib 中的 Path.write_text(data) 函数是否具有原子性。

如果没有,是否存在这样的情况,即文件已经在文件系统中创建,但不包含预期内容?

更具体地说,正如 @ShadowRanger 的评论所建议的那样,我关心的是知道文件是否包含原始数据或新数据,但从未出现过中间状态。实际上,这比完全的原子性要少一些。


在实现中,它基本上使用上下文管理器来编写内容。因此,如果文件已打开(创建),并且写入失败,则上下文退出将使用缓冲区刷新关闭文件。我认为这样的情况是可以预料到的? - Kris
实际上,我知道如何使用通常的Python原语来完成它,就像这里描述的那样https://dev59.com/knE95IYBdhLWcg3wY85l,但是由于pathlib不提供原子标志,所以我想知道它是否不是默认设置。可能会在以后的某个版本中成为选项。 - kriss
1
@kriss:哦,所以你是在问它是否使用任何技巧来确保文件包含要么未修改的旧数据,要么完整的新数据,中间没有任何内容?这并不完全等同于完全原子性,但至少这是你可能关心的事情。 - ShadowRanger
1个回答

2

关于包含原始数据或新数据的文件的特定情况,中间没有任何东西:

不,它并不会通过在同一目录中打开临时文件、填充它,并以原子重命名来替换原始文件。当前实现至少保证有两个唯一操作:

  1. 以写模式打开文件(隐式截断它),以及
  2. 将提供的数据写出(根据数据大小、操作系统API限制和可能中断写操作的信号干扰而可能进行多个系统调用,需要单独的系统调用完成剩余部分)

如果什么都不做,您的代码可能在步骤1之后,步骤2之前死亡(错误时机的Ctrl-C或电源故障),原始数据将消失,没有新数据被写入。

旧答案的原子性概述:

这个问题在表面上看起来无意义。即使它是原子的,在写入发生一纳秒后,其他进程也可以打开该文件,截断它、重写它、移动它等等。甚至在write_text打开文件并写入数据之间,其他进程也可以扫荡并移动/重命名新打开的文件或删除它;当它一秒后写入数据时,write_text保持的打开句柄仍将起作用,但提供路径中的数据将永远不会出现在文件中(并且如果其他进程扫荡并删除它,则可能在write_text关闭它的那一刻消失)。

此外,在任何可移植意义下,甚至在写入过程中,它也不能是原子性的。两个进程可以同时打开同一个文件,并且它们的写操作可以交错执行(在进程内部有关标准处理程序的锁来防止这种情况,但没有这样的锁来与任意其他进程协调)。并发文件I/O很难;尽可能避免。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接