fonctionnalité mkdir-p en Python [dupliquer]

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

Est-il un moyen d'obtenir des fonctionnalités similaires à mkdir -p sur la coque de l'intérieur 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 a déjà écrit?

626
demandé sur Adam Matan 2009-03-01 21:49:39

12 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 optionnel exist_ok cela, lorsqu'il est vrai, active la fonctionnalité mkdir -p - sauf si mode est fourni et le répertoire existant a des autorisations différentes de celles prévues; dans ce cas, OSError est déclenché 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 paramètre exist_ok a été ajouté en Python 3.5.

886
répondu tzot 2017-10-12 12:52:07

En Python > = 3.2, c'est

os.makedirs(path, exist_ok=True)

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

193
répondu Fred Foo 2017-05-23 11:54:59

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

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

Disclaimer 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 vaut mieux 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 ceci réponse, mais je pense qu'il y a de la valeur dans le fil de commentaire ci-dessous. En tant que tel, je le convertit en wiki.

137
répondu Joe Holloway 2016-06-14 15:11:16

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

In [17]: from distutils.dir_util import mkpath

In [18]: mkpath('./foo/bar')
Out[18]: ['foo', 'foo/bar']
42
répondu auraham 2013-01-15 21:39:43

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 affinement de la précédente suggestion serait de re-raise l'exception, si os.path.isdir retourne False (lors de la vérification de errno.EEXIST).

(Update) Voir Aussi cette question très similaire ; je suis d'accord avec la réponse acceptée (et les mises en garde) sauf que je recommanderais os.path.isdir au lieu de os.path.exists.

(Update) 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) 
16
répondu Jacob Gabrielson 2018-06-04 13:49:38

Comme mentionné dans les autres solutions, nous voulons pouvoir 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 à 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 réellement: vous ne pouvez pas dire si quelqu'un a changé le système de fichiers entre-temps. Que s'inscrit également dans le style de Python de demander pardon, pas la permission.

Donc, la première chose que nous devrions faire est d'essayer de créer le répertoire, puis s'il se passe mal, déterminez pourquoi.

Comme le souligne Jacob Gabrielson, 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 en Python serait de déclencher une exception.

Donc, nous devons travailler si cela ce fut le cas. Malheureusement, nous ne pouvons pas. nous recevons le même message d'erreur de makedirs si un répertoire existe (bon) ou un fichier existe empêchant la création du répertoire (mauvais).

La seule façon de comprendre ce qui s'est passé est d'inspecter à nouveau le système de fichiers pour voir s'il y a un répertoire. S'il y en a, alors retournez silencieusement, sinon soulevez 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 quittera silencieusement sans lever d'exception lorsque, au moment du dernier appel système de fichiers, le répertoire existait.

11
répondu c4m3lo 2012-08-08 08:31:24

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

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

Ceux-ci gèrent tous les deux le cas où le chemin existe déjà silencieusement mais laissent apparaître d'autres erreurs.

10
répondu davidavr 2009-03-02 01:47:26

Avec Pathlib de la bibliothèque standard python3:

Path(mypath).mkdir(parents=True, exist_ok=True)

Si parents vaut true, tous les parents manquants de ce chemin sont créés comme suit nécessaire; ils sont créés avec les autorisations par défaut sans prendre mode en compte (imitant la commande POSIX mkdir-p). Si exist_ok a la valeur false (valeur par défaut), un FileExistsError est déclenché si le répertoire cible existe déjà.

Si exist_ok vaut true, les exceptions FileExistsError seront ignorées (idem comportement que l' POSIX mkdir-p), mais seulement si le dernier chemin le composant n'est pas un fichier non-répertoire existant.

Modifié dans la version 3.5: le paramètre exist_ok a été ajouté.

10
répondu Ali SAID OMAR 2016-05-16 07:08:53

Déclaration de Fonction;

import os
def mkdir_p(filename):

    try:
        folder=os.path.dirname(filename)  
        if not os.path.exists(folder):  
            os.makedirs(folder)
        return True
    except:
        return False

Utilisation :

filename = "./download/80c16ee665c8/upload/backup/mysql/2014-12-22/adclient_sql_2014-12-22-13-38.sql.gz"

if (mkdir_p(filename):
    print "Created dir :%s" % (os.path.dirname(filename))
5
répondu Guray Celik 2014-12-22 22:06:56
import os
import tempfile

path = tempfile.mktemp(dir=path)
os.makedirs(path)
os.rmdir(path)
2
répondu pixelbeat 2012-08-06 09:47:43

J'ai eu du succès avec ce qui suit personnellement, mais ma fonction devrait probablement être appelée quelque chose comme 's'assurer que ce répertoire existe':

def mkdirRecursive(dirpath):
    import os
    if os.path.isdir(dirpath): return

    h,t = os.path.split(dirpath) # head/tail
    if not os.path.isdir(h):
        mkdirRecursive(h)

    os.mkdir(join(h,t))
# end mkdirRecursive
2
répondu Dave C 2017-03-15 02:28:07
import os
from os.path import join as join_paths

def mk_dir_recursive(dir_path):

    if os.path.isdir(dir_path):
        return
    h, t = os.path.split(dir_path)  # head/tail
    if not os.path.isdir(h):
        mk_dir_recursive(h)

    new_path = join_paths(h, t)
    if not os.path.isdir(new_path):
        os.mkdir(new_path)

Basé sur la réponse de @Dave C mais avec un bug corrigé où une partie de l'arbre existe déjà

0
répondu Dave00Galloway 2017-05-11 15:35:12