Quelle est la meilleure façon de vérifier si un fichier existe et, sinon, de le créer ?
Réponses
Trop de publicités?Au lieu de os.path.isfile
suggéré par d'autres, je suggère d'utiliser os.path.exists
qui vérifie tout ce qui porte ce nom, et pas seulement s'il s'agit d'un fichier normal.
Ainsi :
if not os.path.exists(filename):
file(filename, 'w').close()
Alternativement :
file(filename, 'w+').close()
Ce dernier va créer le fichier s'il existe, mais pas autrement. En revanche, elle échouera si le fichier existe, mais que vous n'avez pas la permission d'y écrire. C'est pourquoi je préfère la première solution.
Il me semble que toutes les autres réponses ici (jusqu'à présent) ne traitent pas de la condition raciale qui se produit avec les solutions qu'elles proposent.
Tout code dans lequel vous vérifiez d'abord l'existence du fichier, puis, quelques lignes plus loin dans votre programme, vous le créez, court le risque que le fichier soit créé pendant que vous ne regardiez pas et vous cause des problèmes (ou que vous causiez des problèmes au propriétaire de "cet autre fichier").
Si vous voulez éviter ce genre de choses, je vous suggère quelque chose comme ce qui suit (non testé) :
import os
def open_if_not_exists(filename):
try:
fd = os.open(filename, os.O_CREAT | os.O_EXCL | os.O_WRONLY)
except:
print "Ooops"
return None
fobj = os.fdopen(fd, "w")
return fobj
Ceci devrait ouvrir votre fichier pour l'écriture s'il n'existe pas déjà, et retourner un objet-fichier. S'il existe, elle imprimera "Ooops" et retournera None (non testé, et basé uniquement sur la lecture de l'objet la documentation python Il se peut donc qu'il ne soit pas entièrement correct).
Si (lorsque le fichier n'existe pas) vous souhaitez le créer comme vide, l'approche la plus simple est la suivante
with open(thepath, 'a'): pass
(en Python 2.6 ou supérieur ; en 2.5, cela nécessite un "import from the future" en haut de votre module).
Si, d'autre part, vous voulez laisser le fichier intact s'il existe, mais y mettre un contenu spécifique non vide sinon, alors des approches plus compliquées basées sur if os.path.isfile(thepath):
/ else
Les blocs de déclaration sont probablement plus adaptés.
C'était le meilleur moyen pour moi. Vous pouvez récupérer tous les fichiers existants (qu'il s'agisse de liens symboliques ou normaux) :
os.path.lexists(path)
Return True if path refers to an existing path. Returns True for broken symbolic links. Equivalent to exists() on platforms lacking os.lstat().
New in version 2.4.