Quel est le moyen le plus élégant de vérifier si le répertoire dans lequel un fichier va être écrit existe, et si non, créez 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 manière ou d'une autre, 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", ce qui rend cela se produit automatiquement?
Je vois deux réponses de bonnes qualités, chacune avec un petit défaut, je vais donc donner mon point de vue:
Essayez os.path.exists
et considérez os.makedirs
pour 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 critique: si le répertoire est créé entre les appels os.path.exists
et os.makedirs
, le os.makedirs
échouera avec une OSError
. Malheureusement, la capture de OSError
et la poursuite de la couverture ne sont pas infaillibles, car la création du répertoire échouera en raison d'autres facteurs, tels que des autorisations insuffisantes, un disque complet, etc.
Une option serait d’intercepter la OSError
et d’examiner le code d’erreur incorporé (voir Existe-t-il un moyen multi-plateforme 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 avoir un deuxième os.path.exists
, mais supposons qu'un autre ait créé le répertoire après le premier contrôle, puis l'a supprimé avant le second - nous pourrions toujours être dupes.
En fonction de l'application, le danger lié aux opérations simultanées peut être supérieur ou inférieur au danger engendré par d'autres facteurs tels que les autorisations de fichiers. Le développeur devrait en savoir plus sur l’application 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
(in 3.3 +) ...
try:
os.makedirs("path/to/directory")
except FileExistsError:
# directory already exists
pass
... et en autorisant un argument de mot clé à os.makedirs
appelé exist_ok
(in 3.2+).
os.makedirs("path/to/directory", exist_ok=True) # succeeds even if directory exists.
En utilisant try except, le code d'erreur correct du module errno supprime la condition de concurrence critique et est multi-plateforme:
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. D'autre part, toute autre erreur est signalée. Par exemple, si vous créez préalablement un répertoire 'a' et en supprimez toutes les autorisations, vous obtenez une variable OSError
générée avec errno.EACCES
(autorisation refusée, erreur 13).
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.etc
lorsque vous passez cet argument à os.makedirs()
si vous testez avec os.path.exists()
.
Check os.makedirs : (Il s'assure que le chemin complet existe.)
Pour gérer le fait que le répertoire peut exister, récupérez OSError . (Si exist_ok est False (valeur par défaut), une OSError est déclenchée si le répertoire cible existe déjà.)
import os
try:
os.makedirs('./path/to/somewhere')
except OSError:
pass
À partir de Python 3.5, pathlib.Path.mkdir
a un drapeau exist_ok
:
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 le répertoire de manière récursive et ne génère pas d'exception si le répertoire existe déjà.
(juste comme os.makedirs
a un drapeau exist_ok
à partir de python 3.2, par exemple os.makedirs(path, exist_ok=True)
)
Vous donnez un fichier particulier à un certain chemin et vous extrayez le répertoire du chemin de fichier. Ensuite, après vous être assuré que vous avez 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 d’écraser la fonction intégrée, dir
. De plus, filepath
ou peut-être fullfilepath
est probablement un meilleur nom sémantique que filename
, donc ce serait mieux écrit:
import os
filepath = '/my/directory/filename.txt'
directory = os.path.dirname(filepath)
Votre objectif final est d’ouvrir ce fichier, vous avez d’abord indiqué, pour écriture, mais vous vous approchez essentiellement de cet objectif (en fonction de votre code) comme ceci, qui ouvre le fichier pour reading :
if not os.path.exists(directory): os.makedirs(directory) f = file(filename)
Pourquoi voudriez-vous créer un répertoire pour un fichier que vous espérez être là et que vous pourrez 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'existe pas, vous obtiendrez une IOError
avec un numéro d'erreur associé: errno.ENOENT
désignera le numéro d'erreur correct, quelle que soit votre plate-forme. Vous pouvez l'attraper si vous voulez, 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
C'est probablement ce que vous voulez.
Dans ce cas, nous ne sommes probablement pas confrontés à des conditions de concurrence. Donc, faites comme vous étiez, mais notez que pour écrire, vous devez ouvrir avec le mode w
(ou a
à ajouter). Il est également recommandé d'utiliser le gestionnaire de contexte pour ouvrir des fichiers avec Python.
import os
if not os.path.exists(directory):
os.makedirs(directory)
with open(filepath, 'w') as my_file:
do_stuff(my_file)
Cependant, supposons que plusieurs processus Python tentent de placer 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 de placer l'appel makedirs
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)
Essayez la fonction os.path.exists
if not os.path.exists(dir):
os.mkdir(dir)
J'ai mis ce qui suit. Ce n'est pas totalement infaillible cependant.
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.
Vérifier si un répertoire existe et le créer 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 se moquent de votre annuaire:
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 avoir vérifié que le chemin d'accès existe, quelque chose d'autre l'a déjà fait) procédez comme suit:
import errno
try:
os.makedirs(d)
except OSError as exception:
if exception.errno != errno.EEXIST:
raise
Mais peut-être une meilleure solution consiste-t-elle à éviter le problème des conflits de ressources en utilisant des répertoires temporaires via tempfile
:
import tempfile
d = tempfile.mkdtemp()
Voici l'essentiel de la doc 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.
pathlib.Path
avec exist_ok
Il y a un nouvel objet Path
(à partir de la version 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 de code pertinentes du script qui me permettent d'éviter de toucher Stack Overflow plusieurs fois par jour pour les mêmes données.)
D'abord les importations en cause:
from pathlib import Path
import tempfile
Nous n'avons pas à traiter avec os.path.join
maintenant - il suffit de joindre des parties de chemin avec un /
:
directory = Path(tempfile.gettempdir()) / 'sodata'
Je vérifie ensuite que le répertoire existe - l'argument exist_ok
apparaît dans Python 3.5:
directory.mkdir(exist_ok=True)
Voici la partie pertinente de documentation :
Si
exist_ok
est vrai, les exceptionsFileExistsError
seront ignorées (même comportement que la commandePOSIX mkdir -p
), mais uniquement si le dernier composant de chemin d'accès n'est pas un fichier non-répertoire existant.
Voici un peu plus de script - dans mon cas, je ne suis pas soumis à une condition de concurrence, je n'ai qu'un processus qui attend le répertoire (ou les fichiers contenus), 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))
Les objets Path
doivent être forcés à str
avant que les autres API qui attendent des chemins str
puissent les utiliser.
Peut-être que les pandas devraient être mis à jour pour accepter les instances de la classe de base abstraite, os.PathLike
.
En Python 3.4, vous pouvez également utiliser le nouveau module pathlib
:
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.
La documentation Python pertinente suggère l'utilisation du style de codage EAFP (Plus facile de demander pardon que de le permettre) . 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 suggère cela précisément à cause de la situation de concurrence critique décrite dans cette question. En outre, comme d’autres le mentionnent, le fait d’interroger une fois le système d’exploitation présente un avantage en termes de performances. Enfin, l'argument avancé, éventuellement, en faveur du second code dans certains cas - lorsque le développeur connaît l'environnement d'exécution de l'application - ne peut être préconisé que dans le cas particulier où le programme a mis en place un environnement privé. lui-même (et d'autres instances du même programme).
Même dans ce cas, c'est une mauvaise pratique et peut conduire à un long débogage inutile. Par exemple, le fait que nous ayons défini les autorisations pour un répertoire ne doit pas nous laisser l'impression que les autorisations sont définies de manière appropriée pour nos besoins. Un répertoire parent peut être monté avec d'autres autorisations. En général, un programme devrait toujours fonctionner correctement et le programmeur ne devrait pas s'attendre à un environnement spécifique.
Dans Python3, os.makedirs
prend en charge la définition de exist_ok
. Le paramètre par défaut est False
, ce qui signifie qu'une OSError
sera déclenchée si le répertoire cible existe déjà. En définissant exist_ok
sur True
, OSError
(le répertoire existe) sera ignoré et le répertoire ne sera pas créé.
os.makedirs(path,exist_ok=True)
Dans Python2, os.makedirs
ne prend pas en charge le paramétrage 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
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.
J'utilise os.path.exists()
, here est 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 (le cas échéant).
Il invite les utilisateurs à saisir le répertoire et peut être facilement modifié.
Pour une solution one-liner, vous pouvez utiliser IPython.utils.path.ensure_dir_exists()
:
from IPython.utils.path import ensure_dir_exists
ensure_dir_exists(dir)
À partir de documentation : Assurez-vous qu'un répertoire existe. S'il n'existe pas, essayez de le créer et protégez-vous contre une condition de concurrence critique si un autre processus en fait de même.
J'ai vu les réponses de Heikki Toivonen et A-B-B et j'ai pensé à cette variante.
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
Lorsque vous travaillez avec des entrées/sorties de fichiers, l’important est de
Donc, faire une vérification avec if
puis lire ou écrire plus tard peut aboutir à une exception d'E/S non gérée. La meilleure façon de le faire est:
try:
os.makedirs(dir_path)
except OSError as e:
if e.errno != errno.EEXIS:
raise
Vous pouvez utiliser os.listdir
pour cela:
import os
if 'dirName' in os.listdir('parentFolderPath')
print('Directory Exists')
J'ai trouvé cette Q/A et j'étais initialement perplexe devant certains des échecs et des erreurs que je recevais. Je travaille dans Python 3 (v.3.5 dans un environnement virtuel Anaconda sur un système Arch Linux x86_64).
Considérez cette structure de répertoire:
└── output/ ## dir
├── corpus ## file
├── corpus2/ ## dir
└── subdir/ ## dir
Voici mes expériences/notes, qui clarifient les choses:
# ----------------------------------------------------------------------------
# [1] https://stackoverflow.com/questions/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.
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.
Utilisez la bibliothèque pathlib
import pathlib
mypath="/my/directory"
pathlib.Path(mypath).mkdir(parents=True, exist_ok=True)
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')
Utilisez cette commande check et create dir
if not os.path.isdir(test_img_dir):
os.mkdir(str("./"+test_img_dir))
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 pour vous aussi
import os
if os.path.isfile(filename):
print "file exists"
else:
"Your code here"
Où votre code est ici utilisez la commande (tactile)
Cela vérifiera si le fichier est là sinon il le créera.
Pourquoi ne pas utiliser le module de sous-processus s’il s’applique sur un ordinateur prenant en charge les langages Shell? 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.