Quelle est la façon la plus élégante de vérifier si le répertoire dans lequel un fichier va être écrit existe, et sinon, créer le répertoire en utilisant Python? Voici ce que j'ai essayé:
import os
file_path = "/my/directory/filename.txt"
directory = os.path.dirname(file_path)
try:
os.stat(directory)
except:
os.mkdir(directory)
f = file(filename)
D'une certaine manière, j'ai raté os.path.exists
(merci kanja, Blair et Douglas). Voici ce que j'ai maintenant:
def ensure_dir(file_path):
directory = os.path.dirname(file_path)
if not os.path.exists(directory):
os.makedirs(directory)
Existe-t-il un drapeau pour "ouvert", qui rend cela possible automatiquement?
os.path.mkdir
n'existe pas. Ça l'estos.mkdir
.p
, voici mon extrait de code:os.makedirs(p[:p.rindex(os.path.sep)], exist_ok=True)
Réponses:
Sur Python ≥ 3,5, utilisez
pathlib.Path.mkdir
:Pour les anciennes versions de Python, je vois deux réponses avec de bonnes qualités, chacune avec un petit défaut, je vais donc donner mon avis:
Essayez
os.path.exists
et pensezos.makedirs
à la création.Comme indiqué dans les commentaires et ailleurs, il existe une condition de concurrence - si le répertoire est créé entre le
os.path.exists
et lesos.makedirs
appels, leos.makedirs
échouera avec unOSError
. Malheureusement, la captureOSError
et la poursuite des couvertures ne sont pas infaillibles, car elles ignoreront l'échec de la création du répertoire en raison d'autres facteurs, tels que des autorisations insuffisantes, un disque plein, etc.Une option serait de piéger le
OSError
et d'examiner le code d'erreur incorporé (voir Existe - t-il un moyen multiplateforme d'obtenir des informations à partir de OSError de Python ):Alternativement, il pourrait y en avoir un second
os.path.exists
, mais supposons qu'un autre crée le répertoire après la première vérification, puis le supprime avant le second - nous pourrions encore être dupes.Selon l'application, le danger des opérations simultanées peut être supérieur ou inférieur au danger posé par d'autres facteurs tels que les autorisations de fichiers. Le développeur devrait en savoir plus sur l'application particulière en cours de développement et son environnement attendu avant de choisir une implémentation.
Les versions modernes de Python améliorent un peu ce code, à la fois en exposant
FileExistsError
(en 3.3 +) ...... et en permettant à un argument mot-clé d'être
os.makedirs
appeléexist_ok
(en 3.2+).la source
os.path.exists
renvoie égalementTrue
un fichier. J'ai posté une réponse pour résoudre ce problème.exists_ok
paramètre toos.makedirs()
peut être utilisé pour couvrir la façon dont l'existence antérieure du chemin est gérée, depuis Python 3.2.os.mkdirs()
peut créer des dossiers involontaires si un séparateur de chemin est accidentellement omis, le dossier actuel n'est pas comme prévu, un élément de chemin contient le séparateur de chemin. Si vous utilisezos.mkdir()
ces bogues, une exception se produira, vous alertant de leur existence.Python 3.5+:
pathlib.Path.mkdir
comme utilisé ci-dessus crée récursivement le répertoire et ne déclenche pas d'exception si le répertoire existe déjà. Si vous n'avez pas besoin ou souhaitez que les parents soient créés, ignorez l'parents
argument.Python 3.2+:
En utilisant
pathlib
:Si vous le pouvez, installez le
pathlib
backport actuel nommépathlib2
. N'installez pas l'ancien backport non géré nommépathlib
. Ensuite, reportez-vous à la section Python 3.5+ ci-dessus et utilisez-la de la même manière.Si vous utilisez Python 3.4, même s'il est fourni avec
pathlib
, il manque l'exist_ok
option utile . Le backport est destiné à offrir une implémentation plus récente et supérieuremkdir
qui inclut cette option manquante.En utilisant
os
:os.makedirs
comme utilisé ci-dessus crée récursivement le répertoire et ne déclenche pas d'exception si le répertoire existe déjà. Il a l'exist_ok
argument facultatif uniquement si vous utilisez Python 3.2+, avec une valeur par défaut deFalse
. Cet argument n'existe pas dans Python 2.x jusqu'à 2.7. En tant que tel, il n'est pas nécessaire de gérer manuellement les exceptions comme avec Python 2.7.Python 2.7+:
En utilisant
pathlib
:Si vous le pouvez, installez le
pathlib
backport actuel nommépathlib2
. N'installez pas l'ancien backport non géré nommépathlib
. Ensuite, reportez-vous à la section Python 3.5+ ci-dessus et utilisez-la de la même manière.En utilisant
os
:Alors qu'une solution naïve peut d'abord être utilisée,
os.path.isdir
suivie deos.makedirs
la solution ci-dessus inverse l'ordre des deux opérations. Ce faisant, il empêche une condition de concurrence courante ayant à voir avec une tentative dupliquée de création du répertoire, et désambiguïse également les fichiers des répertoires.Notez que la capture de l'exception et son utilisation
errno
sont d'une utilité limitée carOSError: [Errno 17] File exists
, par exempleerrno.EEXIST
, elles sont déclenchées pour les fichiers et les répertoires. Il est plus fiable de simplement vérifier si le répertoire existe.Alternative:
mkpath
crée le répertoire imbriqué et ne fait rien si le répertoire existe déjà. Cela fonctionne à la fois en Python 2 et 3.Selon le bogue 10948 , une grave limitation de cette alternative est qu'elle ne fonctionne qu'une fois par processus python pour un chemin donné. En d'autres termes, si vous l'utilisez pour créer un répertoire, puis supprimez le répertoire à l'intérieur ou à l'extérieur de Python, puis utilisez à
mkpath
nouveau pour recréer le même répertoire,mkpath
utilisera simplement silencieusement ses informations en cache non valides d'avoir créé le répertoire auparavant, et ne le fera pas faire à nouveau le répertoire. En revanche,os.makedirs
ne repose pas sur un tel cache. Cette limitation peut convenir à certaines applications.En ce qui concerne le mode du répertoire , veuillez vous référer à la documentation si vous vous en souciez.
la source
os.path.isdir
une autre personne supprime le dossier, vous provoquerez l'erreur erronée, obsolète et déroutante que ce dossier existe.L'utilisation de try except et du bon code d'erreur du module errno supprime la condition de concurrence et est multiplateforme:
En d'autres termes, nous essayons de créer les répertoires, mais s'ils existent déjà, nous ignorons l'erreur. En revanche, toute autre erreur est signalée. Par exemple, si vous créez à l'avance le répertoire 'a' et en supprimez toutes les autorisations, vous obtiendrez un
OSError
relevé avecerrno.EACCES
(Autorisation refusée, erreur 13).la source
exception.errno != errno.EEXIST
ignorera involontairement le cas où le chemin existe mais est un objet non-répertoire tel qu'un fichier. L'exception devrait idéalement être levée si le chemin est un objet non-répertoire.os.makedirs(path,exist_ok=True)
exist_ok
paramètre a été introduit dans Python 3.2. Il n'est pas présent dans Python 2.x. Je vais l'intégrer dans ma réponse.Je recommanderais personnellement que vous utilisiez
os.path.isdir()
pour tester au lieu deos.path.exists()
.Si tu as:
Et une entrée utilisateur stupide:
... Vous allez vous retrouver avec un répertoire nommé
filename.etc
lorsque vous passez cet argument àos.makedirs()
si vous testez avecos.path.exists()
.la source
Vérifiez
os.makedirs
: (Il s'assure que le chemin d'accès complet existe.)Pour gérer le fait que le répertoire existe, catch
OSError
. (Siexist_ok
estFalse
(par défaut), unOSError
est levé si le répertoire cible existe déjà.)la source
OSError
sera levé ici si le chemin est un fichier ou un répertoire existant. J'ai posté une réponse pour résoudre ce problème.OSError
avant de décider de l'ignorer. Voir stackoverflow.com/a/5032238/763269 .À partir de Python 3.5,
pathlib.Path.mkdir
a unexist_ok
drapeau:Cela crée récursivement le répertoire et ne déclenche pas d'exception si le répertoire existe déjà.
(tout comme
os.makedirs
unexist_ok
drapeau à partir de python 3.2 par exempleos.makedirs(path, exist_ok=True)
)la source
Aperçu des spécificités de cette situation
Vous donnez un fichier particulier à un certain chemin et vous extrayez le répertoire du chemin du fichier. Ensuite, après vous être assuré d'avoir le répertoire, vous essayez d'ouvrir un fichier en lecture. Pour commenter ce code:
Nous voulons éviter la fonction de réécriture builtin,
dir
. Aussi,filepath
ou peutfullfilepath
- être est-ce probablement un meilleur nom sémantique quefilename
ce serait mieux écrit:Votre objectif final est d'ouvrir ce fichier, vous déclarez initialement, pour l'écriture, mais vous approchez essentiellement de cet objectif (basé sur votre code) comme celui-ci, ce qui ouvre le fichier pour la lecture :
En supposant une ouverture pour la lecture
Pourquoi voudriez-vous créer un répertoire pour un fichier que vous attendez et que vous puissiez lire?
Essayez simplement d'ouvrir le fichier.
Si le répertoire ou le fichier n'est pas là, vous obtiendrez un
IOError
avec un numéro d'erreur associé:errno.ENOENT
pointera vers le numéro d'erreur correct quelle que soit votre plate-forme. Vous pouvez l'attraper si vous le souhaitez, par exemple:En supposant que nous ouvrons pour l'écriture
C'est probablement ce que tu veux.
Dans ce cas, nous ne sommes probablement pas confrontés à des conditions de course. Alors, faites comme vous étiez, mais notez que pour écrire, vous devez ouvrir avec le
w
mode (oua
ajouter). Il est également recommandé d'utiliser Python pour utiliser le gestionnaire de contexte pour ouvrir des fichiers.Cependant, disons que nous avons plusieurs processus Python qui tentent de mettre toutes leurs données dans le même répertoire. Ensuite, nous pouvons avoir des conflits sur la création du répertoire. Dans ce cas, il est préférable d'envelopper l'
makedirs
appel dans un bloc try-except.la source
Essayez la
os.path.exists
fonctionla source
os.path.mkdir()
méthode. Le module os.path implémente quelques fonctions utiles sur les chemins d'accès .J'ai mis ce qui suit. Ce n'est cependant pas totalement infaillible.
Maintenant, comme je l'ai dit, ce n'est pas vraiment infaillible, car nous avons la possibilité de ne pas créer le répertoire, et un autre processus le créant pendant cette période.
la source
os.path.exists
- voir stackoverflow.com/a/5032238/763269, et (2) le succès suros.path.exists
ne signifie pas que le répertoire existe, juste que le chemin d'accès existe - pourrait être un fichier, un lien symbolique ou un autre objet du système de fichiers.La réponse directe à cela est, en supposant une situation simple où vous ne vous attendez pas à ce que d'autres utilisateurs ou processus jouent avec votre répertoire:
ou si la création du répertoire est soumise à des conditions de concurrence (c'est-à-dire si après vérification du chemin existe, quelque chose d'autre peut déjà l'avoir fait) faites ceci:
Mais peut-être qu'une approche encore meilleure consiste à contourner le problème de contention des ressources, en utilisant des répertoires temporaires via
tempfile
:Voici l'essentiel du document en ligne:
Nouveau dans Python 3.5:
pathlib.Path
avecexist_ok
Il y a un nouvel
Path
objet (à partir de 3.4) avec beaucoup de méthodes que l'on voudrait utiliser avec des chemins - dont l'un estmkdir
.(Pour le contexte, je surveille mon représentant hebdomadaire avec un script. Voici les parties pertinentes du code du script qui me permettent d'éviter de frapper Stack Overflow plus d'une fois par jour pour les mêmes données.)
D'abord les importations concernées:
Nous n'avons pas à nous occuper
os.path.join
maintenant - il suffit de joindre des parties de chemin avec un/
:Ensuite, je m'assure idempotamment que le répertoire existe - l'
exist_ok
argument apparaît en Python 3.5:Voici la partie pertinente de la documentation :
Voici un peu plus du script - dans mon cas, je ne suis pas soumis à une condition de concurrence, je n'ai qu'un seul processus qui s'attend à ce que le répertoire (ou les fichiers contenus) soit là, et je n'ai rien à essayer de supprimer le répertoire.
Path
les objets doivent être contraintsstr
avant que d'autres API qui s'attendent à ce que lesstr
chemins puissent les utiliser.Peut-être Pandas devrait être mis à jour pour accepter les instances de la classe de base abstraite,
os.PathLike
.la source
Dans Python 3.4, vous pouvez également utiliser le tout nouveau
pathlib
module :la source
pathlib
et oùpathlib2
pour les nouveaux utilisateurs, et je pense que les pros ici trouveront la dépréciation;)La documentation Python pertinente suggère l'utilisation du style de codage EAFP (plus facile à demander pardon qu'à autorisation) . Cela signifie que le code
est meilleur que l'alternative
La documentation le suggère exactement en raison de la condition de concurrence raciale discutée dans cette question. De plus, comme d'autres le mentionnent ici, il y a un avantage en termes de performances à interroger une fois plutôt que deux fois le système d'exploitation. Enfin, l'argument avancé, potentiellement, en faveur du deuxième code dans certains cas - lorsque le développeur connaît l'environnement dans lequel l'application s'exécute - ne peut être avancé que dans le cas particulier où le programme a mis en place un environnement privé pour lui-même (et d'autres instances du même programme).
Même dans ce cas, il s'agit d'une mauvaise pratique et peut conduire à un long débogage inutile. Par exemple, le fait que nous définissions les autorisations pour un répertoire ne devrait pas nous laisser l'impression que les autorisations sont définies de manière appropriée pour nos besoins. Un répertoire parent pourrait être monté avec d'autres autorisations. En général, un programme doit toujours fonctionner correctement et le programmeur ne doit pas s'attendre à un environnement spécifique.
la source
En Python3 ,
os.makedirs
prend en charge la configurationexist_ok
. Le paramètre par défaut estFalse
, ce qui signifie qu'unOSError
sera élevé si le répertoire cible existe déjà. En définissantexist_ok
surTrue
,OSError
(le répertoire existe) sera ignoré et le répertoire ne sera pas créé.En Python2 ,
os.makedirs
ne prend pas en charge la configurationexist_ok
. Vous pouvez utiliser l'approche dans la réponse de heikki-toivonen :la source
Pour une solution monocouche, vous pouvez utiliser
IPython.utils.path.ensure_dir_exists()
:Dans la documentation : Assurez-vous qu'il existe un répertoire. S'il n'existe pas, essayez de le créer et de vous protéger contre une condition de concurrence si un autre processus fait de même.
la source
IPython
présence du module n'est absolument pas garantie. Il est nativement présent sur mon Mac, mais pas sur aucune de mes installations Linux de Python. Fondamentalement, il ne fait pas partie des modules répertoriés dans l' index des modules Python .pip install ipython
ou incluez la dépendance dans votre requirements.txt ou pom.xml . Documentation: ipython.org/install.htmlVous pouvez utiliser
mkpath
Notez qu'il créera également les répertoires ancêtres.
Cela fonctionne pour Python 2 et 3.
la source
distutils.dir_util
ne fait pas partie de l'API publique distutil et a des problèmes dans les environnements multithreads: bugs.python.org/issue10948distutils.dir_util.mkpath
est que si vous créez un répertoire, puis le supprimez de l'intérieur ou de l'extérieur de Python, puis réutilisezmkpath
,mkpath
utilisera simplement ses informations en cache non valides d'avoir créé le répertoire précédemment, et ne pas réellement refaire le répertoire. En revanche,os.makedirs
ne repose pas sur un tel cache.J'utilise
os.path.exists()
, voici un script Python 3 qui peut être utilisé pour vérifier si un répertoire existe, en créer un s'il n'existe pas et le supprimer s'il existe (si vous le souhaitez).Il invite les utilisateurs à saisir le répertoire et peut être facilement modifié.
la source
Vous pouvez utiliser
os.listdir
pour cela:la source
J'ai trouvé ce Q / A et j'ai d'abord été perplexe par certains des échecs et des erreurs que j'obtenais. Je travaille en Python 3 (v.3.5 dans un environnement virtuel Anaconda sur un système Arch Linux x86_64).
Considérez cette structure de répertoires:
Voici mes expériences / notes, qui clarifient les choses:
Conclusion: à mon avis, la "Méthode 2" est plus robuste.
[1] Comment créer un répertoire s'il n'existe pas?
[2] https://docs.python.org/3/library/os.html#os.makedirs
la source
J'ai vu les réponses de Heikki Toivonen et ABB et j'ai pensé à cette variation.
la source
Utilisez cette commande pour vérifier et créer dir
la source
Pourquoi ne pas utiliser le module de sous-processus s'il fonctionne sur une machine qui prend en charge la commande
mkdir
avec-p
option? Fonctionne sur python 2.7 et python 3.6Devrait faire l'affaire sur la plupart des systèmes.
Dans les situations où la portabilité n'a pas d'importance (par exemple, en utilisant docker), la solution est un 2 lignes propres. Vous n'avez pas non plus à ajouter de logique pour vérifier si des répertoires existent ou non. Enfin, il est sûr de réexécuter sans aucun effet secondaire
Si vous avez besoin d'une gestion des erreurs:
la source
Si vous considérez ce qui suit:
signifie qu'un répertoire (chemin) existe ET est un répertoire. Donc, pour moi, cette façon fait ce dont j'ai besoin. Je peux donc m'assurer que c'est un dossier (pas un fichier) et qu'il existe.
la source
Appelez la fonction
create_dir()
au point d'entrée de votre programme / projet.la source
Vous devez définir le chemin complet avant de créer le répertoire:
Cela fonctionne pour moi et j'espère que cela fonctionnera aussi pour vous
la source
Cela vérifiera si le fichier est là s'il ne l'est pas alors il le créera.
la source