2024-04-19 23:03:29 发布
网友
我需要将一个文件从一个位置复制到另一个位置,如果文件已经存在于目标位置(没有覆盖),我需要抛出一个异常(或者至少以某种方式识别)。
我可以先使用os.path.exists()进行检查,但在检查和复制之间的很短时间内无法创建文件是非常重要的。
有没有一种内置的方法可以做到这一点,或者有没有一种方法可以将一个动作定义为原子的?
没有办法做到这一点;文件复制操作从来不是原子的,也没有办法实现它们。
但是你可以用一个随机的,临时的名字写这个文件,然后把它重命名。重命名操作必须是原子的。 如果该文件已经存在,则重命名将失败,您将得到一个错误。
[EDIT2]rename()只有在同一个文件系统中执行时才是原子的。安全的方法是在目标文件夹中创建新文件。
rename()
[编辑]关于重命名是否始终是原子的以及覆盖行为,有很多讨论。所以我挖掘了一些资源。
在Linux上,如果目标存在并且源和目标都是文件,那么目标将被自动覆盖(man page)。所以我错了。
但是rename(2)仍然保证,如果发生错误,原始文件或新文件将保持有效,因此该操作是原子的,因为它不会损坏数据。它不是原子的,因为它阻止两个进程同时执行相同的重命名,并且您可以预测结果。一个人会赢,但你不知道是哪一个。
rename(2)
在Windows上,如果另一个进程当前正在写入文件,则如果尝试打开该文件进行写入,则会出现错误,因此Windows的一个优点是。
如果在将操作写入磁盘时计算机崩溃,则文件系统的实现将决定损坏的数据量。应用程序对此无能为力。所以别再抱怨了:-)
也没有其他方法比这一个更好甚至更好。
你可以用文件锁定代替。但这只会让一切变得更加复杂,不会产生额外的优势(除了变得更加复杂,有些人确实认为这是一个巨大的优势,因为某些原因)。当你的文件在网络驱动器上时,你会添加很多漂亮的角盒。
可以将open(2)与模式O_CREAT一起使用,如果文件已经存在,则会使函数失败。但这不会阻止第二个进程删除文件并编写自己的副本。
open(2)
O_CREAT
或者可以创建一个锁目录,因为创建目录也必须是原子的。但那也买不到多少。你必须自己写锁定代码,并确保绝对,100%确保你真的,真的总是删除锁定目录,以防灾难-你不能
实际上,是实现这一点的一种方法,原子的和安全的,前提是所有参与者都以相同的方式进行。这是对lock-free whack-a-mole algorithm的改编,并不完全是琐碎的,所以请随意使用“no”作为一般答案;)
<target>.<UUID>.tmp
<target>-<UUID>.mole.tmp
<target>-*.mole.tmp
<target>
你完了!
假设每个候选源文件都是一个从洞里出来的鼹鼠。中途,它会暂停并将任何竞争的鼹鼠打回地面,然后再检查没有其他鼹鼠完全出现。如果你在脑子里想清楚了,你会发现只有一只鼹鼠能一路逃出去。为了防止这个系统livelocking,我们添加了一个总的顺序,鼹鼠可以在这个总的顺序上攻击哪个。砰!博士论文。
步骤4可能看起来不必要,为什么不首先使用该名称?然而,在第5步中,另一个过程可能会“采用”您的mole文件,并在第7步中使其成为赢家,因此您不必继续写出内容是非常重要的!在同一个文件系统上重命名是原子的,因此步骤4是安全的。
没有办法做到这一点;文件复制操作从来不是原子的,也没有办法实现它们。
但是你可以用一个随机的,临时的名字写这个文件,然后把它重命名。重命名操作必须是原子的。
如果该文件已经存在,则重命名将失败,您将得到一个错误。[EDIT2]
rename()
只有在同一个文件系统中执行时才是原子的。安全的方法是在目标文件夹中创建新文件。[编辑]关于重命名是否始终是原子的以及覆盖行为,有很多讨论。所以我挖掘了一些资源。
在Linux上,如果目标存在并且源和目标都是文件,那么目标将被自动覆盖(man page)。所以我错了。
但是
rename(2)
仍然保证,如果发生错误,原始文件或新文件将保持有效,因此该操作是原子的,因为它不会损坏数据。它不是原子的,因为它阻止两个进程同时执行相同的重命名,并且您可以预测结果。一个人会赢,但你不知道是哪一个。在Windows上,如果另一个进程当前正在写入文件,则如果尝试打开该文件进行写入,则会出现错误,因此Windows的一个优点是。
如果在将操作写入磁盘时计算机崩溃,则文件系统的实现将决定损坏的数据量。应用程序对此无能为力。所以别再抱怨了:-)
也没有其他方法比这一个更好甚至更好。
你可以用文件锁定代替。但这只会让一切变得更加复杂,不会产生额外的优势(除了变得更加复杂,有些人确实认为这是一个巨大的优势,因为某些原因)。当你的文件在网络驱动器上时,你会添加很多漂亮的角盒。
可以将
open(2)
与模式O_CREAT
一起使用,如果文件已经存在,则会使函数失败。但这不会阻止第二个进程删除文件并编写自己的副本。或者可以创建一个锁目录,因为创建目录也必须是原子的。但那也买不到多少。你必须自己写锁定代码,并确保绝对,100%确保你真的,真的总是删除锁定目录,以防灾难-你不能
实际上,是实现这一点的一种方法,原子的和安全的,前提是所有参与者都以相同的方式进行。这是对lock-free whack-a-mole algorithm的改编,并不完全是琐碎的,所以请随意使用“no”作为一般答案;)
怎么办
<target>.<UUID>.tmp
。<target>-<UUID>.mole.tmp
。<target>-*.mole.tmp
。<target>
。(如果它不见了,不用担心,跳回到第5步。)你完了!
工作原理
假设每个候选源文件都是一个从洞里出来的鼹鼠。中途,它会暂停并将任何竞争的鼹鼠打回地面,然后再检查没有其他鼹鼠完全出现。如果你在脑子里想清楚了,你会发现只有一只鼹鼠能一路逃出去。为了防止这个系统livelocking,我们添加了一个总的顺序,鼹鼠可以在这个总的顺序上攻击哪个。砰!博士论文。
步骤4可能看起来不必要,为什么不首先使用该名称?然而,在第5步中,另一个过程可能会“采用”您的
mole文件,并在第7步中使其成为赢家,因此您不必继续写出内容是非常重要的!在同一个文件系统上重命名是原子的,因此步骤4是安全的。相关问题 更多 >
编程相关推荐