python 中的原子 `ln -sf`(符号链接覆盖现有文件)
Atomic `ln -sf` in python (symlink overwriting exsting file)
我想创建一个符号链接,根据需要覆盖现有文件或符号链接。
我发现 os.path.exists
only returns True
for non-broken symlinks, so I'm guessing that any test must also include os.path.lexists
。
在 python 中实现 ln -sf
的最原子方式是什么? (即,防止文件在删除和符号链接创建之间被另一个进程创建)
区别:This question 未指定原子要求
此代码试图将竞争条件的可能性降至最低:
import os
import tempfile
def symlink_force(target, link_name):
'''
Create a symbolic link link_name pointing to target.
Overwrites link_name if it exists.
'''
# os.replace() may fail if files are on different filesystems
link_dir = os.path.dirname(link_name)
while True:
temp_link_name = tempfile.mktemp(dir=link_dir)
try:
os.symlink(target, temp_link_name)
break
except FileExistsError:
pass
try:
os.replace(temp_link_name, link_name)
except OSError: # e.g. permission denied
os.remove(temp_link_name)
raise
注:
如果功能被中断(例如计算机崩溃),目标可能存在额外的随机link。
不太可能的竞争条件仍然存在:在随机命名的 temp_link_name
上创建的 symlink 可以在替换 link_name
之前被另一个进程修改。
我提出了一个 python issue 来强调 os.symlink()
要求目标不存在的问题。
我想创建一个符号链接,根据需要覆盖现有文件或符号链接。
我发现 os.path.exists
only returns True
for non-broken symlinks, so I'm guessing that any test must also include os.path.lexists
。
在 python 中实现 ln -sf
的最原子方式是什么? (即,防止文件在删除和符号链接创建之间被另一个进程创建)
区别:This question 未指定原子要求
此代码试图将竞争条件的可能性降至最低:
import os
import tempfile
def symlink_force(target, link_name):
'''
Create a symbolic link link_name pointing to target.
Overwrites link_name if it exists.
'''
# os.replace() may fail if files are on different filesystems
link_dir = os.path.dirname(link_name)
while True:
temp_link_name = tempfile.mktemp(dir=link_dir)
try:
os.symlink(target, temp_link_name)
break
except FileExistsError:
pass
try:
os.replace(temp_link_name, link_name)
except OSError: # e.g. permission denied
os.remove(temp_link_name)
raise
注:
如果功能被中断(例如计算机崩溃),目标可能存在额外的随机link。
不太可能的竞争条件仍然存在:在随机命名的
temp_link_name
上创建的 symlink 可以在替换link_name
之前被另一个进程修改。
我提出了一个 python issue 来强调 os.symlink()
要求目标不存在的问题。