Python - 覆盖 link(如果存在)

Python - overwrite a link if it exists

from os import link

link('WInd_Rose_Aguiar.svg', 'Wikipedia Daily Featured Picture')

# A day has passed

link('Piero_del_Pollaiuolo_-_Profile_Portrait_of_a_Young_Lady_-_Gemäldegalerie_Berlin_-_Google_Art_Project.jpg',
     'Wikipedia Daily Featured Picture') # Exception

调用上述脚本的结果:

my@comp:~/wtfdir$ python3 wtf.py
Traceback (most recent call last):
  File "wtf.py", line 8, in <module>
    'Wikipedia Daily Featured Picture') # Exception
FileExistsError: [Errno 17] File exists: 'Piero_del_Pollaiuolo_-_Profile_Portrait_of_a_Young_Lady_-_Gemäldegalerie_Berlin_-_Google_Art_Project.jpg' -> 'Wikipedia Daily Featured Picture'

创建第一个 link 成功。创建第二个失败。

这完全出乎我的意料……我的目的是覆盖这个link。

https://docs.python.org/3/library/os.html#os.link ⇐ 我在文档中看不到 forceoverwrite_if_exists 或函数 link 的类似参数。

如何创建一个指向新源的 link,如果存在则覆盖之前的 link?

嗯,是的——我想我可以这样做:

from os import link, remove
from os.path import isfile

def force_link(src, dest):
    if isfile(dest):
        remove(dest)
    link(src, dest)

force_link('WInd_Rose_Aguiar.svg', 'Wikipedia Daily Featured Picture')

# A day has passed

force_link('Piero_del_Pollaiuolo_-_Profile_Portrait_of_a_Young_Lady_-_Gemäldegalerie_Berlin_-_Google_Art_Project.jpg',
     'Wikipedia Daily Featured Picture') # No longer exception

但这很麻烦,至少在理论上可能是不正确的(如果其他进程在 remove(dest)link(src, dest) 之间重新创建文件怎么办?)。虽然也许可以解决这个(至少理论上的)不正确性,但生成的代码会更加繁琐,我想......

一定有更好的、更适合右手的方法!

为您要公开的文件创建一个新的 link。然后将固定的 link 替换为您刚刚创建的新 link。

from tempfile import TemporaryDirectory


def force_link(src, dest):
    with TemporaryDirectory(dir=os.path.dirname(dest)) as d:
        tmpname = os.path.join(d, "foo")
        os.link(src, tmpname)
        os.replace(tmpname, dest)

之后您可能需要确保 dest 上的权限是正确的。

os.link 将成功在临时目录中安全地创建一个新的 link。然后,您将使用 os.replace 安全地将临时 link 重命名为 dest,有效地用新的 link 覆盖旧的 link。