Question mkdir -p fonctionnalité en Python [dupliquer]


Cette question a déjà une réponse ici:

Existe-t-il un moyen d'obtenir des fonctionnalités similaires à mkdir -p sur le shell de Python. Je suis à la recherche d'une solution autre qu'un appel système. Je suis sûr que le code est inférieur à 20 lignes, et je me demande si quelqu'un l'a déjà écrit?


617
2018-03-01 18:49


origine


Réponses:


mkdir -p fonctionnalité comme suit:

import errno    
import os


def mkdir_p(path):
    try:
        os.makedirs(path)
    except OSError as exc:  # Python >2.5
        if exc.errno == errno.EEXIST and os.path.isdir(path):
            pass
        else:
            raise

Mettre à jour

Pour Python ≥ 3.2, os.makedirs a un troisième argument facultatif  exist_ok que, lorsque cela est vrai, permet mkdir -p fonctionnalité -sauf si  mode est fourni et le répertoire existant a des autorisations différentes de celles prévues; dans ce cas, OSError est élevé comme précédemment.

Mise à jour 2

Pour Python ≥ 3.5, il y a aussi pathlib.Path.mkdir:

import pathlib

pathlib.Path("/tmp/path/to/desired/directory").mkdir(parents=True, exist_ok=True)

le exist_ok paramètre a été ajouté dans Python 3.5.


869
2018-03-01 21:51



En Python> = 3.2, c'est

os.makedirs(path, exist_ok=True)

Dans les versions antérieures, utilisez La réponse de @ tzot.


189
2018-06-19 13:21



C'est plus facile que de piéger l'exception:

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

Avertissement Cette approche nécessite deux appels système qui sont plus sensibles aux conditions de course dans certains environnements / conditions. Si vous écrivez quelque chose de plus sophistiqué qu'un simple script jetable s'exécutant dans un environnement contrôlé, il est préférable d'utiliser la réponse acceptée qui ne nécessite qu'un seul appel système.

MISE À JOUR 2012-07-27

Je suis tenté de supprimer cette réponse, mais je pense qu'il y a de la valeur dans le fil de commentaires ci-dessous. En tant que tel, je le convertis en wiki.


135
2018-01-15 21:39



Récemment, j'ai trouvé ça distutils.dir_util.mkpath:

In [17]: from distutils.dir_util import mkpath

In [18]: mkpath('./foo/bar')
Out[18]: ['foo', 'foo/bar']

39
2018-03-02 00:09



mkdir -p vous donne une erreur si le fichier existe déjà:

$ touch /tmp/foo
$ mkdir -p /tmp/foo
mkdir: cannot create directory `/tmp/foo': File exists

Donc, un raffinement des suggestions précédentes serait deraise l'exception si os.path.isdir résultats False (en vérifiant pour errno.EEXIST).

(Mise à jour) Voir aussi cette question très similaire; Je suis d'accord avec la réponse acceptée (et les réserves) sauf que je recommanderais os.path.isdir au lieu de os.path.exists.

(Mise à jour) Selon une suggestion dans les commentaires, la fonction complète ressemblerait à:

import os
def mkdirp(directory):
    if not os.path.isdir(directory):
        os.makedirs(directory) 

13
2017-08-08 08:31



Comme mentionné dans les autres solutions, nous voulons être capable de frapper le système de fichiers une fois tout en imitant le comportement de mkdir -p. Je ne pense pas que ce soit possible, mais nous devrions nous rapprocher le plus possible.

Code d'abord, explication plus tard:

import os
import errno

def mkdir_p(path):
    """ 'mkdir -p' in Python """
    try:
        os.makedirs(path)
    except OSError as exc:  # Python >2.5
        if exc.errno == errno.EEXIST and os.path.isdir(path):
            pass
        else:
            raise

Comme les commentaires sur la réponse de @ tzot indiquent qu'il y a des problèmes à vérifier si vous pouvez créer un répertoire avant de le créer: vous ne pouvez pas dire si quelqu'un a changé le système de fichiers entre-temps. Cela correspond également au style de demande de Python pour le pardon, pas la permission.

Donc, la première chose que nous devrions faire est d'essayer de faire le répertoire, puis si ça ne va pas, élucider pourquoi.

Comme Jacob Jacobelson le souligne, l'un des cas que nous devons rechercher est le cas où un fichier existe déjà où nous essayons de mettre le répertoire.

Avec mkdir -p:

$ touch /tmp/foo
$ mkdir -p /tmp/foo
mkdir: cannot create directory '/tmp/foo': File exists

Le comportement analogue dans Python serait de lever une exception.

Nous devons donc travailler si c'était le cas. Malheureusement, nous ne pouvons pas. Makedirs renvoie le même message d'erreur si un répertoire existe (bon) ou s'il existe un fichier empêchant la création du répertoire (mauvais).

La seule façon de déterminer ce qui s'est passé est d'inspecter à nouveau le système de fichiers pour voir s'il existe un répertoire. S'il y en a, alors revenez en silence, sinon augmentez l'exception.

Le seul problème est que le système de fichiers peut être dans un état différent maintenant que lorsque makedirs a été appelé. Par exemple: un fichier existait provoquant l'échec de makedirs, mais maintenant un répertoire est à sa place. Cela n'a pas vraiment d'importance, car la fonction ne sortira que silencieusement sans déclencher une exception lorsque le répertoire a existé lors du dernier appel du système de fichiers.


10
2018-03-01 21:47



Je pense que la réponse d'Asa est essentiellement correcte, mais vous pouvez l'étendre un peu pour agir plus comme mkdir -p, non plus:

import os

def mkdir_path(path):
    if not os.access(path, os.F_OK):
        os.mkdirs(path)

ou

import os
import errno

def mkdir_path(path):
    try:
        os.mkdirs(path)
    except os.error, e:
        if e.errno != errno.EEXIST:
            raise

Ils traitent tous les deux le cas où le chemin existe déjà en mode silencieux, mais laissent filtrer d'autres erreurs.


9
2018-02-08 17:02