Ror*_*ory 10 python concurrency
我需要将文件从一个位置复制到另一个位置,如果文件已存在于目标位置(无覆盖),我需要抛出异常(或至少以某种方式识别).
我可以先用os.path.exists()检查,但是在检查和复制之间的少量时间内无法创建文件是非常重要的.
是否有内置的方法来实现这一点,或者有没有办法将动作定义为原子?
Aar*_*lla 13
没有办法做到这一点; 文件复制操作永远不是原子的,也没有办法制作它们.
但您可以使用随机的临时名称编写该文件,然后重命名该文件.重命名操作必须是原子的.如果该文件已存在,则重命名将失败,您将收到错误.
rename()如果在同一文件系统中执行,[EDIT2]只是原子的.安全的方法是在与目标相同的文件夹中创建新文件.
[编辑]有很多关于重命名是否始终是原子的以及关于覆盖行为的讨论.所以我挖出了一些资源.
在Linux上,如果目标存在且源和目标都是文件,则会以静默方式覆盖目标(手册页).所以我错了.
但是rename(2)仍然保证原始文件或新文件在出现问题时仍然有效,因此操作是原子的,因为它不能破坏数据.从某种意义上讲,它不是原子的,它可以阻止两个进程同时进行相同的重命名,并且可以预测结果.一个人会赢,但你不知道哪个.
在Windows上,如果另一个进程当前正在编写该文件,如果您尝试将其打开以进行编写,则会出现错误,因此Windows的一个优点就在这里.
如果在将操作写入磁盘时计算机崩溃,则文件系统的实现将决定损坏的数据量.有没有什么应用程序可以做到这一点.所以停止抱怨已经:-)
也没有其他方法可以更好地工作,甚至也不如此方法.
您可以使用文件锁定.但这只会使一切变得更加复杂并且不会产生额外的优势(除了更复杂,有些人确实认为这是一个巨大的优势).当你的文件在网络驱动器上时,你会添加许多漂亮的角落案例.
如果文件已存在,您可以使用会使函数失败open(2)的模式O_CREAT.但这不会阻止第二个进程删除文件并编写自己的副本.
或者你可以创建一个锁目录,因为创建目录也必须是原子的.但这也不会给你带来太大的收益.你必须亲自编写锁定代码,并且绝对,100%确定你真的,真的总是在发生灾难时删除锁定目录 - 你不能这样做.
还有就是其实是一个办法做到这一点,原子和安全,提供的所有演员都以相同的方式.它是对无锁whack-a-mole算法的改编,并不是完全无关紧要的,所以请随意使用"否"作为一般答案;)
<target>.<UUID>.tmp.<target>-<UUID>.mole.tmp.<target>-*.mole.tmp.
<target>.(不要担心,如果它消失了,只需跳回到第5步.)你完成了!
想象一下,每个候选源文件都是一个鼹鼠.在检查没有其他鼹鼠完全出现之前,它会暂停并将任何竞争的鼹鼠重击回地面.如果你在头脑中经历这一过程,你应该看到只有一颗痣会完全消失.为了防止这个系统发生活锁,我们添加了一个可以敲打哪个痣的总排序.巴姆!一个 博士论文 的无锁算法.
†步骤4可能看起来不必要 - 为什么不首先使用该名称?但是,另一个过程可能会在步骤5中"采用"你的 鼹鼠 文件,并使其成为第7步中的胜利者,所以你还没有写出内容是非常重要的!在同一文件系统上重命名是原子的,因此第4步是安全的.
| 归档时间: |
|
| 查看次数: |
6336 次 |
| 最近记录: |