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

Les résultats de l'appel du script ci-dessus :

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'

La création du premier lien réussit. La création du second échoue.

Ce n'est guère ce à quoi je m'attendrais… Mon intention est d'écraser ce lien.

https://docs.python.org/3/library/os. html#os.link ⇐ Je ne vois pas de force ou overwrite_if_exists ou paramètre similaire à la fonction link dans la doc.

Comment puis-je créer un lien pointant vers une nouvelle source, en écrasant le lien précédent s'il existe ?

Eh bien oui, je suppose que je peux faire qc comme ça :

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

Mais cela est lourd et au moins en théorie peut être incorrect (et si un autre processus recrée le fichier entre remove(dest) et link(src, dest) ?). Et bien que cette inexactitude (au moins théorique) puisse être résolue, le code résultant serait encore plus lourd, je suppose…

Il doit y avoir une meilleure façon, plus droitière de le faire !

0
user4385532 20 nov. 2019 à 17:22

1 réponse

Meilleure réponse

Créez un nouveau lien pour le fichier que vous souhaitez exposer. Remplacez ensuite votre lien fixe par le nouveau lien que vous venez de créer.

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)

Vous devrez peut-être vous assurer que les autorisations sur dest sont correctes par la suite.

os.link réussira à créer en toute sécurité un nouveau lien dans le répertoire temporaire. Vous utiliserez ensuite os.replace pour renommer en toute sécurité le lien temporaire en dest, en remplaçant efficacement l'ancien lien par le nouveau.

3
gaazkam 20 nov. 2019 à 17:01