我需要将文件从一个位置复制到另一个位置,如果文件已存在于目的地(不覆盖),我需要抛出异常(或至少以某种方式识别)。
我可以首先使用 os.path.exists() 检查,但极其重要的是,不能在检查和复制之间的短时间内创建文件。
是否有一种内置的方法可以做到这一点,或者有没有一种方法可以将操作定义为原子操作?
There is事实上,有一种方法可以原子地、安全地做到这一点,前提是所有演员都以同样的方式做。这是一个改编无锁打地鼠算法 http://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-697.pdf#page=66,而且并非完全微不足道,因此请随意选择“否”作为一般答案;)
该怎么办
- 检查文件是否已经存在。如果有就停下来。
- 生成唯一ID https://docs.python.org/2/library/uuid.html#uuid.uuid4
- 将源文件复制到目标文件夹,并使用临时名称,例如,
<target>.<UUID>.tmp
.
- Rename† the copy
<target>-<UUID>.mole.tmp
.
-
Look for any other files matching the pattern https://docs.python.org/2/library/glob.html
<target>-*.mole.tmp
.
- 如果他们的 UUID 比你的大,尝试删除它 https://docs.python.org/2/library/os.html#os.remove。 (如果它消失了,请不要担心。)
- 如果他们的 UUID 小于您的,请尝试删除您自己的。 (再次强调,如果它消失了,请不要担心。)从现在开始,将他们的 UUID 视为您自己的 UUID。
- 再次检查目标文件是否已存在。如果是这样,请尝试删除您的临时文件。 (如果它消失了,请不要担心。记住您的 UUID 可能在第 5 步中已更改。)
- 如果您尚未在第 6 步中尝试将其删除,请尝试将临时文件重命名为其最终名称,
<target>
。 (如果它消失了,不用担心,只需跳回步骤 5。)
你完成了!
怎么运行的
想象每个候选源文件都是一个从洞里钻出来的鼹鼠。中途,它会停下来,将任何竞争的鼹鼠打回地面,然后检查是否有其他鼹鼠完全出现。如果你在脑子里仔细想一想,你应该会发现只有一颗鼹鼠能够一路逃出去。为了防止该系统活锁 https://en.wikipedia.org/wiki/Deadlock#Livelock,我们添加了总排序,即哪只鼹鼠可以攻击哪只鼹鼠。嘭! 博士论文无锁算法 https://en.wikipedia.org/wiki/Non-blocking_algorithm#Lock-freedom.
† Step 4 may look unnecessary—why not just use that name in the first place? However, another process may "adopt" your mole file in step 5, and make it the winner in step 7, so it's very important that you're not still writing out the contents! Renames on the same file system are atomic, so step 4 is safe.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)