Comment créer en toute sécurité un répertoire imbriqué?

4253

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?

Parand
la source
27
En général, vous devrez peut-être tenir compte du cas où il n'y a pas de répertoire dans le nom de fichier. Sur ma machine, dirname ('foo.txt') donne '', qui n'existe pas et fait échouer makedirs ().
Brian Hawkins
11
En python 2.7 os.path.mkdirn'existe pas. Ça l'est os.mkdir.
drevicko
6
si le chemin existe il faut non seulement vérifier s'il s'agit d'un répertoire et non d'un fichier normal ou d'un autre objet (beaucoup de réponses le vérifient) il faut aussi vérifier s'il est accessible en écriture (je n'ai pas trouvé de réponse qui l'a vérifié)
miracle173
9
Dans le cas où vous êtes venu ici pour créer des répertoires parents de la chaîne de chemin de fichier p, voici mon extrait de code:os.makedirs(p[:p.rindex(os.path.sep)], exist_ok=True)
Thamme Gowda

Réponses:

5197

Sur Python ≥ 3,5, utilisez pathlib.Path.mkdir:

from pathlib import Path
Path("/my/directory").mkdir(parents=True, exist_ok=True)

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.existset pensez os.makedirsà la création.

import os
if not os.path.exists(directory):
    os.makedirs(directory)

Comme indiqué dans les commentaires et ailleurs, il existe une condition de concurrence - si le répertoire est créé entre le os.path.existset les os.makedirsappels, le os.makedirséchouera avec un OSError. Malheureusement, la capture OSErroret 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 OSErroret d'examiner le code d'erreur incorporé (voir Existe - t-il un moyen multiplateforme d'obtenir des informations à partir de OSError de Python ):

import os, errno

try:
    os.makedirs(directory)
except OSError as e:
    if e.errno != errno.EEXIST:
        raise

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 +) ...

try:
    os.makedirs("path/to/directory")
except FileExistsError:
    # directory already exists
    pass

... et en permettant à un argument mot-clé d'être os.makedirsappeléexist_ok (en 3.2+).

os.makedirs("path/to/directory", exist_ok=True)  # succeeds even if directory exists.
Blair Conrad
la source
5
La condition de concurrence est un bon point, mais l'approche dans stackoverflow.com/questions/273192/#273208 masquera l' échec de la création du répertoire. Ne vous sentez pas mal de voter contre - vous n'aimez pas la réponse. C'est à cela que servent les votes.
Blair Conrad
27
N'oubliez pas que os.path.exists () n'est pas gratuit. Si le cas normal est que le répertoire sera là, alors le cas où il ne l'est pas doit être traité comme une exception. En d'autres termes, essayez d'ouvrir et d'écrire dans votre fichier, interceptez l'exception OSError et, basé sur errno, faites votre makedir () et réessayez ou relancez. Cela crée une duplication de code sauf si vous encapsulez l'écriture dans une méthode locale.
Andrew
22
os.path.existsrenvoie également Trueun fichier. J'ai posté une réponse pour résoudre ce problème.
Acumenus
13
Comme l'ont noté les commentateurs d'autres réponses ici, le exists_okparamètre to os.makedirs()peut être utilisé pour couvrir la façon dont l'existence antérieure du chemin est gérée, depuis Python 3.2.
Bobble
6
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 utilisez os.mkdir()ces bogues, une exception se produira, vous alertant de leur existence.
drevicko
1242

Python 3.5+:

import pathlib
pathlib.Path('/my/directory').mkdir(parents=True, exist_ok=True) 

pathlib.Path.mkdircomme 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' parentsargument.

Python 3.2+:

En utilisant pathlib:

Si vous le pouvez, installez le pathlibbackport 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_okoption utile . Le backport est destiné à offrir une implémentation plus récente et supérieure mkdirqui inclut cette option manquante.

En utilisant os:

import os
os.makedirs(path, exist_ok=True)

os.makedirscomme 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_okargument facultatif uniquement si vous utilisez Python 3.2+, avec une valeur par défaut de False. 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 pathlibbackport 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:

import os
try: 
    os.makedirs(path)
except OSError:
    if not os.path.isdir(path):
        raise

Alors qu'une solution naïve peut d'abord être utilisée, os.path.isdirsuivie de os.makedirsla 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 errnosont d'une utilité limitée car OSError: [Errno 17] File exists, par exemple errno.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:

mkpathcré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.

import distutils.dir_util
distutils.dir_util.mkpath(path)

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 à mkpathnouveau pour recréer le même répertoire, mkpathutilisera 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.makedirsne 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.

Acumenus
la source
13
Pour autant que je sache, cette réponse couvre à peu près tous les cas particuliers. Je prévois d'envelopper cela dans un "sinon os.path.isdir ()" bien que puisque je m'attends à ce que le répertoire existe presque à chaque fois et je peux éviter l'exception de cette façon.
Charles L.
5
@CharlesL. Une exception est probablement moins chère que le disque IO du chèque, si votre raison est la performance.
jpmc26
1
@ jpmc26 mais makedirs fait des statistiques supplémentaires, umask, lstat en vérifiant uniquement pour lancer OSError.
kwarunek
4
Ce n'est pas la bonne réponse, car elle introduit un potentiel de course FS. Voir la réponse d'Aaron Hall.
sleepycal
4
comme l'a dit @sleepycal, cela souffre d'une condition de concurrence similaire à la réponse acceptée. Si entre le signalement de l'erreur et la vérification d' os.path.isdirune autre personne supprime le dossier, vous provoquerez l'erreur erronée, obsolète et déroutante que ce dossier existe.
farmir
604

L'utilisation de try except et du bon code d'erreur du module errno supprime la condition de concurrence et est multiplateforme:

import os
import errno

def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST:
            raise

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 OSErrorrelevé avec errno.EACCES(Autorisation refusée, erreur 13).

Heikki Toivonen
la source
24
La réponse acceptée est en fait dangereuse car elle a une condition de race. C'est plus simple, cependant, donc si vous n'êtes pas au courant de la condition de race, ou pensez que cela ne s'applique pas à vous, ce serait votre premier choix évident.
Heikki Toivonen
15
Déclencher l'exception uniquement lorsque exception.errno != errno.EEXISTignorera 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.
Acumenus
178
Notez que le code ci-dessus est équivalent àos.makedirs(path,exist_ok=True)
Navin
58
@Navin Le exist_okparamè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.
Acumenus
26
@HeikkiToivonen Techniquement parlant, si un autre programme modifie les répertoires et les fichiers en même temps que votre programme, votre programme entier est une condition de course géante. Qu'est-ce qui empêche un autre programme de simplement supprimer ce répertoire après que le code l'ait créé et avant d'y mettre des fichiers?
jpmc26
102

Je recommanderais personnellement que vous utilisiez os.path.isdir()pour tester au lieu de os.path.exists().

>>> os.path.exists('/tmp/dirname')
True
>>> os.path.exists('/tmp/dirname/filename.etc')
True
>>> os.path.isdir('/tmp/dirname/filename.etc')
False
>>> os.path.isdir('/tmp/fakedirname')
False

Si tu as:

>>> dir = raw_input(":: ")

Et une entrée utilisateur stupide:

:: /tmp/dirname/filename.etc

... Vous allez vous retrouver avec un répertoire nommé filename.etclorsque vous passez cet argument à os.makedirs()si vous testez avec os.path.exists().

Peter Mortensen
la source
8
Si vous utilisez uniquement 'isdir', ne rencontrez-vous toujours pas de problème lorsque vous essayez de créer le répertoire et qu'un fichier du même nom existe déjà?
MrWonderful
3
@MrWonderful L'exception résultante lors de la création d'un répertoire sur un fichier existant refléterait correctement le problème à l'appelant.
Damian Yerrick
79

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. (Si exist_okest False(par défaut), un OSErrorest levé si le répertoire cible existe déjà.)

import os
try:
    os.makedirs('./path/to/somewhere')
except OSError:
    pass
Douglas Mayle
la source
19
avec le try / except, vous masquerez les erreurs dans la création du répertoire, dans le cas où le répertoire n'existait pas mais pour une raison quelconque vous ne pouvez pas le faire
Blair Conrad
3
OSErrorsera 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.
Acumenus
4
C'est à mi-chemin. Vous devez vérifier la condition de sous-erreur OSErroravant de décider de l'ignorer. Voir stackoverflow.com/a/5032238/763269 .
Chris Johnson
71

À partir de Python 3.5, pathlib.Path.mkdira un exist_okdrapeau:

from pathlib import Path
path = Path('/my/directory/filename.txt')
path.parent.mkdir(parents=True, exist_ok=True) 
# path.parent ~ os.path.dirname(path)

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.makedirsun exist_okdrapeau à partir de python 3.2 par exemple os.makedirs(path, exist_ok=True))

hiro protagoniste
la source
46

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:

filename = "/my/directory/filename.txt"
dir = os.path.dirname(filename)

Nous voulons éviter la fonction de réécriture builtin, dir. Aussi, filepathou peut fullfilepath- être est-ce probablement un meilleur nom sémantique que filenamece serait mieux écrit:

import os
filepath = '/my/directory/filename.txt'
directory = os.path.dirname(filepath)

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 :

if not os.path.exists(directory):
    os.makedirs(directory)
f = file(filename)

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.

with open(filepath) as my_file:
    do_stuff(my_file)

Si le répertoire ou le fichier n'est pas là, vous obtiendrez un IOErroravec un numéro d'erreur associé: errno.ENOENTpointera vers le numéro d'erreur correct quelle que soit votre plate-forme. Vous pouvez l'attraper si vous le souhaitez, par exemple:

import errno
try:
    with open(filepath) as my_file:
        do_stuff(my_file)
except IOError as error:
    if error.errno == errno.ENOENT:
        print 'ignoring error because directory or file is not there'
    else:
        raise

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 wmode (ou aajouter). Il est également recommandé d'utiliser Python pour utiliser le gestionnaire de contexte pour ouvrir des fichiers.

import os
if not os.path.exists(directory):
    os.makedirs(directory)
with open(filepath, 'w') as my_file:
    do_stuff(my_file)

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' makedirsappel dans un bloc try-except.

import os
import errno
if not os.path.exists(directory):
    try:
        os.makedirs(directory)
    except OSError as error:
        if error.errno != errno.EEXIST:
            raise
with open(filepath, 'w') as my_file:
    do_stuff(my_file)
Aaron Hall
la source
34

Essayez la os.path.existsfonction

if not os.path.exists(dir):
    os.mkdir(dir)
disparu
la source
3
J'allais commenter la question, mais entendons-nous os.mkdir? Mon python (2.5.2) n'a pas os.path.mkdir ....
Blair Conrad
1
Il n'y a pas de os.path.mkdir()méthode. Le module os.path implémente quelques fonctions utiles sur les chemins d'accès .
Serge S.21
31

J'ai mis ce qui suit. Ce n'est cependant pas totalement infaillible.

import os

dirname = 'create/me'

try:
    os.makedirs(dirname)
except OSError:
    if os.path.exists(dirname):
        # We are nearly safe
        pass
    else:
        # There was an error on creation, so make sure we know about it
        raise

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.

Ali Afshar
la source
Deux problèmes: (1) vous devez vérifier la condition de sous-erreur d'OSError avant de décider de vérifier os.path.exists- voir stackoverflow.com/a/5032238/763269, et (2) le succès sur os.path.existsne 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.
Chris Johnson
24

Vérifiez si un répertoire existe et créez-le si nécessaire?

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:

if not os.path.exists(d):
    os.makedirs(d)

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:

import errno
try:
    os.makedirs(d)
except OSError as exception:
    if exception.errno != errno.EEXIST:
        raise

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:

import tempfile

d = tempfile.mkdtemp()

Voici l'essentiel du document en ligne:

mkdtemp(suffix='', prefix='tmp', dir=None)
    User-callable function to create and return a unique temporary
    directory.  The return value is the pathname of the directory.

    The directory is readable, writable, and searchable only by the
    creating user.

    Caller is responsible for deleting the directory when done with it.

Nouveau dans Python 3.5: pathlib.Pathavecexist_ok

Il y a un nouvel Pathobjet (à partir de 3.4) avec beaucoup de méthodes que l'on voudrait utiliser avec des chemins - dont l'un est mkdir.

(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:

from pathlib import Path
import tempfile

Nous n'avons pas à nous occuper os.path.joinmaintenant - il suffit de joindre des parties de chemin avec un /:

directory = Path(tempfile.gettempdir()) / 'sodata'

Ensuite, je m'assure idempotamment que le répertoire existe - l' exist_okargument apparaît en Python 3.5:

directory.mkdir(exist_ok=True)

Voici la partie pertinente de la documentation :

Si la valeur exist_okest true, les FileExistsErrorexceptions seront ignorées (même comportement que la POSIX mkdir -pcommande), mais uniquement si le dernier composant de chemin n'est pas un fichier non répertoire existant.

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.

todays_file = directory / str(datetime.datetime.utcnow().date())
if todays_file.exists():
    logger.info("todays_file exists: " + str(todays_file))
    df = pd.read_json(str(todays_file))

Pathles objets doivent être contraints stravant que d'autres API qui s'attendent à ce que les strchemins puissent les utiliser.

Peut-être Pandas devrait être mis à jour pour accepter les instances de la classe de base abstraite, os.PathLike.

Aaron Hall
la source
20

Dans Python 3.4, vous pouvez également utiliser le tout nouveau pathlibmodule :

from pathlib import Path
path = Path("/my/directory/filename.txt")
try:
    if not path.parent.exists():
        path.parent.mkdir(parents=True)
except OSError:
    # handle error; you can also catch specific errors like
    # FileExistsError and so on.
Antti Haapala
la source
@JanuszSkonieczny pypi.python.org/pypi/pathlib2 est le nouveau backport. L'ancien n'est pas entretenu.
Acumenus
Comme il l'a indiqué dans la première ligne du fichier Lisezmoi: P. Mais l'ancien backport est toujours valable pour la réponse ici. Et il n'y a pas de mal de tête. Pas besoin d'expliquer pourquoi et quand utiliser pathlibet où pathlib2pour les nouveaux utilisateurs, et je pense que les pros ici trouveront la dépréciation;)
Janusz Skonieczny
13

La documentation Python pertinente suggère l'utilisation du style de codage EAFP (plus facile à demander pardon qu'à autorisation) . Cela signifie que le code

try:
    os.makedirs(path)
except OSError as exception:
    if exception.errno != errno.EEXIST:
        raise
    else:
        print "\nBE CAREFUL! Directory %s already exists." % path

est meilleur que l'alternative

if not os.path.exists(path):
    os.makedirs(path)
else:
    print "\nBE CAREFUL! Directory %s already exists." % path

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.

kavadias
la source
12

En Python3 , os.makedirsprend en charge la configuration exist_ok. Le paramètre par défaut est False, ce qui signifie qu'un OSErrorsera élevé si le répertoire cible existe déjà. En définissant exist_oksur True, OSError(le répertoire existe) sera ignoré et le répertoire ne sera pas créé.

os.makedirs(path,exist_ok=True)

En Python2 , os.makedirsne prend pas en charge la configuration exist_ok. Vous pouvez utiliser l'approche dans la réponse de heikki-toivonen :

import os
import errno

def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST:
            raise
euccas
la source
11

Pour une solution monocouche, vous pouvez utiliser IPython.utils.path.ensure_dir_exists():

from IPython.utils.path import ensure_dir_exists
ensure_dir_exists(dir)

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.

tashuhka
la source
Nouvelle documentation IPython disponible ici .
jkdev
3
La IPythonpré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 .
Acumenus
1
Sûr. Pour installer le package, exécutez simplement l'habituel pip install ipythonou incluez la dépendance dans votre requirements.txt ou pom.xml . Documentation: ipython.org/install.html
tashuhka
9

Vous pouvez utiliser mkpath

# Create a directory and any missing ancestor directories. 
# If the directory already exists, do nothing.

from distutils.dir_util import mkpath
mkpath("test")    

Notez qu'il créera également les répertoires ancêtres.

Cela fonctionne pour Python 2 et 3.

Dennis Golomazov
la source
2
distutils.dir_utilne fait pas partie de l'API publique distutil et a des problèmes dans les environnements multithreads: bugs.python.org/issue10948
Pod
1
Oui. Comme indiqué dans le premier message du bogue, le problème avec distutils.dir_util.mkpathest que si vous créez un répertoire, puis le supprimez de l'intérieur ou de l'extérieur de Python, puis réutilisez mkpath, mkpathutilisera 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.makedirsne repose pas sur un tel cache.
Acumenus
8

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é.

Michael Strobel
la source
6

Vous pouvez utiliser os.listdirpour cela:

import os
if 'dirName' in os.listdir('parentFolderPath')
    print('Directory Exists')
iPhynx
la source
Cela ne répond pas à la question
Georgy
6

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:

└── output/         ## dir
   ├── corpus       ## file
   ├── corpus2/     ## dir
   └── subdir/      ## dir

Voici mes expériences / notes, qui clarifient les choses:

# ----------------------------------------------------------------------------
# [1] /programming/273192/how-can-i-create-a-directory-if-it-does-not-exist

import pathlib

""" Notes:
        1.  Include a trailing slash at the end of the directory path
            ("Method 1," below).
        2.  If a subdirectory in your intended path matches an existing file
            with same name, you will get the following error:
            "NotADirectoryError: [Errno 20] Not a directory:" ...
"""
# Uncomment and try each of these "out_dir" paths, singly:

# ----------------------------------------------------------------------------
# METHOD 1:
# Re-running does not overwrite existing directories and files; no errors.

# out_dir = 'output/corpus3'                ## no error but no dir created (missing tailing /)
# out_dir = 'output/corpus3/'               ## works
# out_dir = 'output/corpus3/doc1'           ## no error but no dir created (missing tailing /)
# out_dir = 'output/corpus3/doc1/'          ## works
# out_dir = 'output/corpus3/doc1/doc.txt'   ## no error but no file created (os.makedirs creates dir, not files!  ;-)
# out_dir = 'output/corpus2/tfidf/'         ## fails with "Errno 20" (existing file named "corpus2")
# out_dir = 'output/corpus3/tfidf/'         ## works
# out_dir = 'output/corpus3/a/b/c/d/'       ## works

# [2] https://docs.python.org/3/library/os.html#os.makedirs

# Uncomment these to run "Method 1":

#directory = os.path.dirname(out_dir)
#os.makedirs(directory, mode=0o777, exist_ok=True)

# ----------------------------------------------------------------------------
# METHOD 2:
# Re-running does not overwrite existing directories and files; no errors.

# out_dir = 'output/corpus3'                ## works
# out_dir = 'output/corpus3/'               ## works
# out_dir = 'output/corpus3/doc1'           ## works
# out_dir = 'output/corpus3/doc1/'          ## works
# out_dir = 'output/corpus3/doc1/doc.txt'   ## no error but creates a .../doc.txt./ dir
# out_dir = 'output/corpus2/tfidf/'         ## fails with "Errno 20" (existing file named "corpus2")
# out_dir = 'output/corpus3/tfidf/'         ## works
# out_dir = 'output/corpus3/a/b/c/d/'       ## works

# Uncomment these to run "Method 2":

#import os, errno
#try:
#       os.makedirs(out_dir)
#except OSError as e:
#       if e.errno != errno.EEXIST:
#               raise
# ----------------------------------------------------------------------------

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

Victoria Stuart
la source
6

J'ai vu les réponses de Heikki Toivonen et ABB et j'ai pensé à cette variation.

import os
import errno

def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST or not os.path.isdir(path):
            raise
alissonmuller
la source
6

Utilisez cette commande pour vérifier et créer dir

 if not os.path.isdir(test_img_dir):
     os.mkdir(test_img_dir)
Manivannan Murugavel
la source
5

Pourquoi ne pas utiliser le module de sous-processus s'il fonctionne sur une machine qui prend en charge la commande mkdiravec -poption? Fonctionne sur python 2.7 et python 3.6

from subprocess import call
call(['mkdir', '-p', 'path1/path2/path3'])

Devrait 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:

from subprocess import check_call
try:
    check_call(['mkdir', '-p', 'path1/path2/path3'])
except:
    handle...
Geoff Paul Bremner
la source
4

Si vous considérez ce qui suit:

os.path.isdir('/tmp/dirname')

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.

Ralph Schwerdt
la source
Comment cela répond-il à une question de création d' un répertoire?
Georgy
3

Appelez la fonction create_dir()au point d'entrée de votre programme / projet.

import os

def create_dir(directory):
    if not os.path.exists(directory):
        print('Creating Directory '+directory)
        os.makedirs(directory)

create_dir('Project directory')
Steffi Keran Rani J
la source
3

Vous devez définir le chemin complet avant de créer le répertoire:

import os,sys,inspect
import pathlib

currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
your_folder = currentdir + "/" + "your_folder"

if not os.path.exists(your_folder):
   pathlib.Path(your_folder).mkdir(parents=True, exist_ok=True)

Cela fonctionne pour moi et j'espère que cela fonctionnera aussi pour vous

Hussam Kurd
la source
1
import os
if os.path.isfile(filename):
    print "file exists"
else:
    "Your code here"

Où se trouve votre code ici, utilisez la commande (tactile)

Cela vérifiera si le fichier est là s'il ne l'est pas alors il le créera.

Le mal existe
la source