Pregunta Funcionalidad mkdir -p en Python [duplicado]


Esta pregunta ya tiene una respuesta aquí:

¿Hay alguna manera de obtener una funcionalidad similar a mkdir -p en el shell desde dentro de Python. Estoy buscando una solución que no sea una llamada al sistema. Estoy seguro de que el código tiene menos de 20 líneas, y me pregunto si alguien ya lo ha escrito.


617
2018-03-01 18:49


origen


Respuestas:


mkdir -p funcionalidad de la siguiente manera:

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

Actualizar

Para Python ≥ 3.2, os.makedirs tiene un Tercer argumento opcional  exist_ok eso, cuando es verdadero, habilita el mkdir -p funcionalidad -a no ser que  mode se proporciona y el directorio existente tiene permisos diferentes a los previstos; en ese caso, OSError se plantea como anteriormente.

Actualización 2

Para Python ≥ 3.5, también hay pathlib.Path.mkdir:

import pathlib

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

los exist_ok parámetro fue agregado en Python 3.5.


869
2018-03-01 21:51



En Python> = 3.2, eso es

os.makedirs(path, exist_ok=True)

En versiones anteriores, use @ tzot respuesta.


189
2018-06-19 13:21



Esto es más fácil que atrapar la excepción:

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

Renuncia Este enfoque requiere dos llamadas al sistema que son más susceptibles a las condiciones de carrera en ciertos entornos / condiciones. Si está escribiendo algo más sofisticado que un simple script desechable que se ejecuta en un entorno controlado, es mejor que vaya con la respuesta aceptada que requiere solo una llamada al sistema.

ACTUALIZACIÓN 2012-07-27

Estoy tentado de eliminar esta respuesta, pero creo que hay un valor en el hilo de comentarios a continuación. Como tal, lo estoy convirtiendo a una wiki.


135
2018-01-15 21:39



Recientemente, encontré esto 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 le da un error si el archivo ya existe:

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

Entonces, un refinamiento a las sugerencias anteriores sería volver araise la excepción si os.path.isdir devoluciones False (cuando se busca errno.EEXIST)

(Actualización) Vea también esto pregunta muy similar; Estoy de acuerdo con la respuesta aceptada (y advertencias) excepto que recomendaría os.path.isdir en lugar de os.path.exists.

(Actualización) Según una sugerencia en los comentarios, la función completa se vería así:

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

13
2017-08-08 08:31



Como se mencionó en las otras soluciones, queremos poder acceder al sistema de archivos una vez mientras imitamos el comportamiento de mkdir -p. No creo que esto sea posible, pero debemos acercarnos lo más posible.

Primero el código, explicación después:

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

Como los comentarios a la respuesta de @ tzot indican que hay problemas para verificar si puede crear un directorio antes de que realmente lo cree: no puede decir si alguien ha cambiado el sistema de archivos mientras tanto. Eso también encaja con el estilo de Python de pedir perdón, no permiso.

Entonces, lo primero que debemos hacer es tratar de crear el directorio, luego, si sale mal, averiguar por qué.

Como señala Jacob Gabrielson, uno de los casos que debemos buscar es el caso donde ya existe un archivo en el que intentamos colocar el directorio.

Con mkdir -p:

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

El comportamiento análogo en Python sería generar una excepción.

Entonces tenemos que averiguar si este fue el caso. Lamentablemente, no podemos. Recibimos el mismo mensaje de error de makedirs sobre si existe un directorio (bueno) o si existe un archivo que impide la creación del directorio (incorrecto).

La única forma de resolver lo sucedido es inspeccionar el sistema de archivos nuevamente para ver si hay un directorio allí. Si lo hay, devuélvalo en silencio, de lo contrario, presente la excepción.

El único problema es que el sistema de archivos puede estar en un estado diferente ahora que cuando se llamó a makedirs. por ejemplo: existía un archivo que causaba que makedirs fallara, pero ahora hay un directorio en su lugar. Eso realmente no importa mucho, porque la función solo saldrá silenciosamente sin generar una excepción cuando en el momento de la última llamada al sistema de archivos existía el directorio.


10
2018-03-01 21:47



Creo que la respuesta de Asa es esencialmente correcta, pero podrías extenderla un poco para que se parezca más a mkdir -p, ya sea:

import os

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

o

import os
import errno

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

Ambos manejan el caso donde la ruta ya existe silenciosamente pero permiten que otros errores aparezcan.


9
2018-02-08 17:02



Con Pathlib de la biblioteca estándar python3:

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

Si los padres son ciertos, los padres desaparecidos de esta ruta se crean como   necesario; se crean con los permisos predeterminados sin tomar   modo en cuenta (imitando el comando POSIX mkdir -p).   Si existe_ok es falso (el valor predeterminado), se genera un FileExistsError si   el directorio de destino ya existe.

Si exist_ok es verdadero, las excepciones FileExistsError se ignorarán (mismas   comportamiento como el comando POSIX mkdir -p), pero solo si la última ruta   componente no es un archivo existente no de directorio.

Modificado en la versión 3.5: El parámetro exist_ok fue agregado.


9
2017-12-22 22:06



Declaración de función;

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

uso:

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

4
2017-08-06 09:47