¿Cómo creo un directorio y los directorios principales que faltan?

10 minutos de lectura

Avatar de usuario de Parand
Parand

¿Cómo creo un directorio en una ruta determinada y también creo los directorios principales que faltan a lo largo de esa ruta? Por ejemplo, el comando Bash mkdir -p /path/to/nested/directory Haz esto.

  • En general, es posible que deba tener en cuenta el caso en el que no hay un directorio en el nombre del archivo. En mi máquina, dirname(‘foo.txt’) da ”, que no existe y hace que makedirs() falle.

    –Brian Hawkins

    26 mayo 2010 a las 23:30

  • si la ruta existe, uno no solo tiene que verificar si es un directorio y no un archivo normal u otro objeto (muchas respuestas verifican esto), también es necesario verificar si se puede escribir (no encontré una respuesta que verificó esto)

    – milagro173

    19 de febrero de 2014 a las 19:52

  • En caso de que haya venido aquí para crear directorios principales de cadena de ruta de archivo paquí está mi fragmento de código: os.makedirs(p[:p.rindex(os.path.sep)], exist_ok=True)

    – Thamme Gowda

    25 de octubre de 2016 a las 3:40

  • En Windows 10, si estoy en el explorador de archivos y se muestra el directorio, entonces python (usando 3.7.4) dará ‘el archivo existe’ cuando intento crear el directorio y tengo exist_ok=True. Cuando cierro el explorador de archivos y vuelvo a ejecutar el programa python, funciona bien.

    – bruce

    26/10/2022 a las 21:46

Avatar de usuario de Blair Conrad
Blair Conrado

En Python ≥ 3.5, use pathlib.Path.mkdir:

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

Para versiones anteriores de Python, veo dos respuestas con buenas cualidades, cada una con un pequeño defecto, así que daré mi opinión:

Intentar os.path.existsy considera os.makedirs para la creación.

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

Como se indica en los comentarios y en otros lugares, hay una condición de carrera: si el directorio se crea entre el os.path.exists y el os.makedirs llamadas, la os.makedirs fallará con un OSError. Desafortunadamente, la captura de mantas OSError y continuar no es infalible, ya que ignorará un error al crear el directorio debido a otros factores, como permisos insuficientes, disco lleno, etc.

Una opción sería atrapar al OSError y examine el código de error incrustado (consulte ¿Existe una forma multiplataforma de obtener información del OSError de Python):

import os, errno

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

Alternativamente, podría haber una segunda os.path.existspero supongamos que otro creó el directorio después de la primera verificación y luego lo eliminó antes de la segunda; aún podríamos ser engañados.

Dependiendo de la aplicación, el peligro de las operaciones simultáneas puede ser mayor o menor que el peligro que representan otros factores, como los permisos de archivos. El desarrollador tendría que saber más sobre la aplicación en particular que se está desarrollando y su entorno esperado antes de elegir una implementación.

Las versiones modernas de Python mejoran bastante este código, tanto al exponer FileExistsError (en 3.3+)…

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

…y al permitir un argumento de palabra clave para os.makedirs llamado exist_ok (en 3.2+).

os.makedirs("path/to/directory", exist_ok=True)  # succeeds even if directory exists.

  • La condición de carrera es un buen punto, pero el enfoque en stackoverflow.com/questions/273192/#273208 enmascarará una falla al crear el directorio. No se sienta mal por votar en contra, no le gusta la respuesta. Para eso están los votos.

    – Blair Conrado

    7 de noviembre de 2008 a las 20:35

  • Recuerde que os.path.exists() no es gratuito. Si el caso normal es que el directorio estará allí, entonces el caso en el que no lo esté debe manejarse como una excepción. En otras palabras, intente abrir y escribir en su archivo, detecte la excepción OSError y, en función de errno, haga su makedir() y vuelva a intentarlo o volver a subir. Esto crea una duplicación de código a menos que ajuste la escritura en un método local.

    – Andrés

    28 de noviembre de 2011 a las 19:10


  • os.path.exists también regresa True para un archivo. He publicado una respuesta para abordar esto.

    – Asclepio

    14/02/2013 a las 17:32

  • Como han señalado los comentaristas de otras respuestas aquí, el exists_ok parámetro a os.makedirs() se puede usar para cubrir cómo se maneja la existencia previa de la ruta, ya que Python 3.2.

    – Bobble

    20 de mayo de 2013 a las 6:50

  • os.mkdirs() puede crear carpetas no deseadas si un separador de ruta se omite accidentalmente, la carpeta actual no es la esperada, un elemento de ruta contiene el separador de ruta. Si utiliza os.mkdir() estos errores generarán una excepción, alertándolo de su existencia.

    – drevicko

    6 de julio de 2013 a las 6:41

Avatar de usuario de Asclepius
Asclepio

Pitón 3.5+:

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

pathlib.Path.mkdir como se usó anteriormente, crea recursivamente el directorio y no genera una excepción si el directorio ya existe. Si no necesita o no desea que se creen los padres, omita el parents argumento.

Pitón 3.2+:

Usando pathlib:

Si puede, instale el actual pathlib backport nombrado pathlib2. No instale el backport no mantenido más antiguo llamado pathlib. A continuación, consulte la sección Python 3.5+ anterior y utilícelo de la misma manera.

Si usa Python 3.4, aunque viene con pathlible falta lo util exist_ok opción. El backport está destinado a ofrecer una implementación más nueva y superior de mkdir que incluye esta opción que falta.

Usando os:

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

os.makedirs como se usó anteriormente, crea recursivamente el directorio y no genera una excepción si el directorio ya existe. tiene el opcional exist_ok argumento solo si usa Python 3.2+, con un valor predeterminado de False. Este argumento no existe en Python 2.x hasta 2.7. Como tal, no hay necesidad de manejo manual de excepciones como con Python 2.7.

Pitón 2.7+:

Usando pathlib:

Si puede, instale el actual pathlib backport nombrado pathlib2. No instale el backport no mantenido más antiguo llamado pathlib. A continuación, consulte la sección Python 3.5+ anterior y utilícelo de la misma manera.

Usando os:

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

Si bien una solución ingenua puede usar primero os.path.isdir seguido por os.makedirs, la solución anterior invierte el orden de las dos operaciones. Al hacerlo, evita una condición de carrera común que tiene que ver con un intento duplicado de crear el directorio y también elimina la ambigüedad de los archivos de los directorios.

Tenga en cuenta que capturar la excepción y usar errno tiene una utilidad limitada porque OSError: [Errno 17] File existses decir errno.EEXIST, se genera tanto para archivos como para directorios. Es más confiable simplemente verificar si el directorio existe.

Alternativa:

mkpath crea el directorio anidado y no hace nada si el directorio ya existe. Esto funciona tanto en Python 2 como en 3. Tenga en cuenta, sin embargo, que distutils ha quedado en desuso y su eliminación está programada en Python 3.12.

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

Por error 10948, una limitación importante de esta alternativa es que solo funciona una vez por proceso de Python para una ruta determinada. En otras palabras, si lo usa para crear un directorio, elimine el directorio desde dentro o fuera de Python, luego use mkpath de nuevo para recrear el mismo directorio, mkpath simplemente usará silenciosamente su información almacenada en caché no válida de haber creado previamente el directorio, y en realidad no volverá a crear el directorio. A diferencia de, os.makedirs no depende de tal caché. Esta limitación puede estar bien para algunas aplicaciones.


Con respecto al directorio modoconsulte la documentación si le interesa.

  • Esta respuesta cubre casi todos los casos especiales, por lo que puedo decir. Planeo envolver esto en un “if not os.path.isdir()”, ya que espero que el directorio exista casi siempre y puedo evitar la excepción de esa manera.

    – Carlos L.

    26 de abril de 2013 a las 5:52


  • @CharlesL. Una excepción es probablemente más barata que la E/S del disco de la verificación, si su motivo es el rendimiento.

    – jpmc26

    29/04/2014 a las 22:39


  • @ jpmc26 pero makedirs hace estadísticas adicionales, umask, lstat cuando solo verifica para lanzar OSError.

    – kwarunek

    19/09/2014 a las 10:31


  • Esta es la respuesta incorrecta, ya que introduce una posible condición de carrera de FS. Ver respuesta de Aaron Hall.

    – Sleepy Cal

    08/01/2016 a las 15:20

  • como ha dicho @sleepycal, esto sufre una condición de carrera similar a la respuesta aceptada. Si entre el aumento del error y la comprobación os.path.isdir Si alguien más elimina la carpeta, generará el error incorrecto, desactualizado y confuso de que la carpeta existe.

    – farmear

    27 de abril de 2016 a las 7:20

Avatar de usuario de Heikki Toivonen
Heikki Toivonen

Usar try except y el código de error correcto del módulo errno elimina la condición de carrera y es multiplataforma:

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 otras palabras, intentamos crear los directorios, pero si ya existen ignoramos el error. Por otro lado, se informa cualquier otro error. Por ejemplo, si crea el directorio ‘a’ de antemano y le quita todos los permisos, obtendrá un OSError criado con errno.EACCES (Permiso denegado, error 13).

  • La respuesta aceptada es realmente peligrosa porque tiene una condición de carrera. Sin embargo, es más simple, por lo que si no conoce la condición de carrera o cree que no se aplicará a usted, esa sería su primera elección obvia.

    –Heikki Toivonen

    7 mayo 2012 a las 18:23

  • Generar la excepción solo cuando exception.errno != errno.EEXIST ignorará involuntariamente el caso cuando la ruta existe pero es un objeto que no es un directorio, como un archivo. Idealmente, la excepción debería generarse si la ruta no es un objeto de directorio.

    – Asclepio

    16 de enero de 2013 a las 17:13

  • Tenga en cuenta que el código anterior es equivalente a os.makedirs(path,exist_ok=True)

    – Navin

    9 de febrero de 2013 a las 15:36

  • @Navin El exist_ok El parámetro se introdujo en Python 3.2. No está presente en Python 2.x. Lo incorporaré en mi respuesta.

    – Asclepio

    14 de febrero de 2013 a las 17:46

  • @HeikkiToivonen Técnicamente hablando, si otro programa está modificando los directorios y archivos al mismo tiempo que su programa, todo su programa es una condición de carrera gigante. ¿Qué impide que otro programa simplemente elimine este directorio después de que el código lo crea y antes de que realmente coloque archivos en él?

    – jpmc26

    29/04/2014 a las 22:41


avatar de usuario de hiro protagonista
hiro protagonista

A partir de Python 3.5, pathlib.Path.mkdir tiene un exist_ok bandera:

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

Esto crea recursivamente el directorio y no genera una excepción si el directorio ya existe.

(Tal como os.makedirs consiguió una exist_ok bandera a partir de python 3.2, por ejemplo os.makedirs(path, exist_ok=True))


Nota: cuando publiqué esta respuesta, ninguna de las otras respuestas mencionadas exist_ok

Yo personalmente recomendaría que usted use os.path.isdir() probar en lugar 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 usted tiene:

>>> directory = raw_input(":: ")

Y una entrada de usuario tonta:

:: /tmp/dirname/filename.etc

… Vas a terminar con un directorio llamado filename.etc cuando pasas ese argumento a os.makedirs() si pruebas con os.path.exists().

Avatar de usuario de Georgy
georgia

Controlar os.makedirs: (Se asegura de que exista la ruta completa).
Para manejar el hecho de que el directorio podría existir, capture OSError. (Si exist_ok es False (el predeterminado), un OSError se genera si el directorio de destino ya existe).

import os
try:
    os.makedirs('./path/to/somewhere')
except OSError:
    pass

avatar de usuario de jesterjunk
bufón

Prueba el os.path.exists función

if not os.path.exists(dir):
    os.mkdir(dir)

¿Ha sido útil esta solución?