¿Cuál es la forma más elegante de verificar si el directorio en el que se va a escribir un archivo existe, y si no, crear el directorio usando Python? Esto es lo que probé:

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)

De alguna manera, me perdí os.path.exists (gracias kanja, Blair y Douglas). Esto es lo que tengo ahora:

def ensure_dir(file_path):
    directory = os.path.dirname(file_path)
    if not os.path.exists(directory):
        os.makedirs(directory)

¿Hay una bandera para "abrir", que hace que esto suceda automáticamente?

4081
Parand 7 nov. 2008 a las 21:56

25 respuestas

La mejor respuesta

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

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

Para las versiones anteriores de Python, veo dos respuestas con buenas cualidades, cada una con un pequeño defecto, por lo que daré mi opinión al respecto:

Pruebe os.path.exists, y considere os.makedirs para la creación.

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

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

Una opción sería atrapar el OSError y examinar 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 un segundo os.path.exists, pero supongamos que otro creó el directorio después de la primera verificación, luego lo eliminó antes de la segunda, aún podríamos engañarnos.

Dependiendo de la aplicación, el peligro de operaciones concurrentes puede ser más o menos que el peligro que representan otros factores, como los permisos de archivos. El desarrollador tendría que saber más sobre la aplicación 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 {{X0} } (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 { {X1}} (en 3.2+).

os.makedirs("path/to/directory", exist_ok=True)  # succeeds even if directory exists.
4957
Boris 30 dic. 2019 a las 09:23

¿Comprobar si existe un directorio y crearlo si es necesario?

La respuesta directa a esto es, suponiendo una situación simple en la que no esperes que otros usuarios o procesos estén jugando con tu directorio:

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

o si hacer que el directorio esté sujeto a condiciones de carrera (es decir, si después de verificar que la ruta existe, es posible que algo más ya lo haya hecho) haga esto:

import errno
try:
    os.makedirs(d)
except OSError as exception:
    if exception.errno != errno.EEXIST:
        raise

Pero quizás un enfoque aún mejor es evitar el problema de contención de recursos, utilizando directorios temporales a través de tempfile:

import tempfile

d = tempfile.mkdtemp()

Aquí están los elementos esenciales del documento en línea:

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.

Nueva en Python 3.5: pathlib.Path con exist_ok

Hay un nuevo objeto Path (a partir de 3.4) con muchos métodos que uno desearía usar con rutas, uno de los cuales es mkdir.

(Por contexto, estoy rastreando mi representante semanal con un script. Aquí están las partes relevantes del código del script que me permiten evitar golpear Stack Overflow más de una vez al día por los mismos datos).

Primero las importaciones relevantes:

from pathlib import Path
import tempfile

No tenemos que lidiar con os.path.join ahora, solo une las partes de la ruta con un /:

directory = Path(tempfile.gettempdir()) / 'sodata'

Luego, me aseguro de que el directorio exista: el argumento exist_ok aparece en Python 3.5:

directory.mkdir(exist_ok=True)

Aquí está la parte relevante de la documentación:

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

Aquí hay un poco más del script: en mi caso, no estoy sujeto a una condición de carrera, solo tengo un proceso que espera que el directorio (o archivos contenidos) esté allí, y no tengo nada que intente eliminar El directorio.

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

Los objetos Path tienen que ser obligados a str antes de que otras API que esperan rutas str puedan usarlos.

Quizás Pandas debería actualizarse para aceptar instancias de la clase base abstracta, os.PathLike.

24
Aaron Hall 7 jul. 2017 a las 03:19

Use este comando check y cree dir

 if not os.path.isdir(test_img_dir):
     os.mkdir(test_img_dir)
5
Jean-François Fabre 16 may. 2019 a las 19:07

Si considera lo siguiente:

os.path.isdir('/tmp/dirname')

Significa que existe un directorio (ruta) Y es un directorio. Entonces para mí de esta manera hace lo que necesito. Entonces puedo asegurarme de que sea una carpeta (no un archivo) y que exista.

4
Ralph Schwerdt 3 dic. 2016 a las 16:35
import os
if os.path.isfile(filename):
    print "file exists"
else:
    "Your code here"

Donde su código aquí es use el comando (táctil)

Esto verificará si el archivo está allí, si no lo está, lo creará.

1
Evil Exists 5 jul. 2017 a las 23:15

¿Por qué no utilizar el módulo de subproceso si se ejecuta en una máquina que admite comandos? ¿mkdir con la opción -p? Funciona en python 2.7 y python 3.6

from subprocess import call
call(['mkdir', '-p', 'path1/path2/path3'])

Debería hacer el truco en la mayoría de los sistemas.

En situaciones en las que la portabilidad no importa (por ejemplo, usando Docker), la solución es limpiar 2 líneas. Tampoco tiene que agregar lógica para verificar si existen directorios o no. Finalmente, es seguro volver a ejecutar sin efectos secundarios.

Si necesita manejo de errores:

from subprocess import check_call
try:
    check_call(['mkdir', '-p', 'path1/path2/path3'])
except:
    handle...
5
Jean-François Fabre 16 may. 2019 a las 19:37

Debe configurar la ruta completa antes de crear el directorio:

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)

Esto funciona para mí y, con suerte, también funcionará para ti

3
Hussam Kurd 19 may. 2019 a las 00:40

Puede usar os.listdir para esto:

import os
if 'dirName' in os.listdir('parentFolderPath')
    print('Directory Exists')
6
dippas 30 sep. 2017 a las 12:31

Pruebe el {{ Función X0}}

if not os.path.exists(dir):
    os.mkdir(dir)
32
jesterjunk 15 oct. 2015 a las 16:05

Python 3.5+:

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

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

Python 3.2+:

Uso de pathlib:

Si puede, instale el puerto pathlib actual llamado pathlib2. No instale el backport sin mantenimiento anterior llamado pathlib. A continuación, consulte la sección Python 3.5+ anterior y úsela igual.

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

Uso de os:

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

os.makedirs como se usa arriba crea el directorio de forma recursiva y no generar una excepción si el directorio ya existe. Tiene el argumento opcional exist_ok 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.

Python 2.7+:

Uso de pathlib:

Si puede, instale el puerto pathlib actual llamado pathlib2. No instale el backport sin mantenimiento anterior llamado pathlib. A continuación, consulte la sección Python 3.5+ anterior y úsela igual.

Uso de os:

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

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

Tenga en cuenta que capturar la excepción y usar errno es de utilidad limitada porque OSError: [Errno 17] File exists, es decir, errno.EEXIST, se genera para archivos y 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 en Python 2 y 3.

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

Según Bug 10948, una limitación severa de esta alternativa es que funciona solo una vez por proceso de Python para una ruta determinada . En otras palabras, si lo usa para crear un directorio, luego elimine el directorio desde dentro o fuera de Python, luego use mkpath nuevamente para recrear el mismo directorio, mkpath simplemente usará en silencio su información en caché no válida de haber creado previamente el directorio y no volverá a crearlo. Por el contrario, os.makedirs no se basa en tal caché. Esta limitación puede estar bien para algunas aplicaciones.


Con respecto al modo del directorio, consulte la documentación si le interesa.

1214
Acumenus 17 may. 2018 a las 17:16

La documentación relevante de Python sugiere el uso de la Estilo de codificación EAFP (más fácil pedir perdón que permiso). Esto significa que el código

try:
    os.makedirs(path)
except OSError as exception:
    if exception.errno != errno.EEXIST:
        raise
    else:
        print "\nBE CAREFUL! Directory %s already exists." % path

Es mejor que la alternativa

if not os.path.exists(path):
    os.makedirs(path)
else:
    print "\nBE CAREFUL! Directory %s already exists." % path

La documentación sugiere esto exactamente debido a la condición de carrera discutida en esta pregunta. Además, como otros mencionan aquí, existe una ventaja de rendimiento al consultar una vez en lugar del doble del sistema operativo. Finalmente, el argumento presentado, potencialmente, a favor del segundo código en algunos casos, cuando el desarrollador conoce el entorno en el que se ejecuta la aplicación, solo se puede defender en el caso especial de que el programa haya establecido un entorno privado para en sí (y otras instancias del mismo programa).

Incluso en ese caso, esta es una mala práctica y puede conducir a una depuración inútil durante mucho tiempo. Por ejemplo, el hecho de que establezcamos los permisos para un directorio no debería dejarnos con la impresión de que los permisos están configurados adecuadamente para nuestros propósitos. Un directorio padre podría montarse con otros permisos. En general, un programa siempre debe funcionar correctamente y el programador no debe esperar un entorno específico.

13
Peter Mortensen 31 dic. 2017 a las 03:12

En Python 3.4 también puede usar el nuevo módulo 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.
20
Antti Haapala 11 mar. 2015 a las 20:50

Yo personalmente recomendaría que use os.path.isdir() para 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:

>>> dir = raw_input(":: ")

Y una entrada tonta del usuario:

:: /tmp/dirname/filename.etc

... Va a terminar con un directorio llamado filename.etc cuando pase ese argumento a os.makedirs() si prueba con os.path.exists().

101
Peter Mortensen 31 may. 2014 a las 14:06

En Python3 , os.makedirs admite la configuración exist_ok. La configuración predeterminada es False, lo que significa que se generará un OSError si el directorio de destino ya existe. Al configurar exist_ok en True, OSError (el directorio existe) se ignorará y el directorio no se creará.

os.makedirs(path,exist_ok=True)

En Python2 , os.makedirs no admite la configuración exist_ok. Puede utilizar el enfoque en respuesta 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
10
Community 23 may. 2017 a las 12:26

Percepciones sobre los detalles de esta situación.

Usted proporciona un archivo en particular en una ruta determinada y extrae el directorio de la ruta del archivo. Luego, después de asegurarse de tener el directorio, intenta abrir un archivo para leerlo. Para comentar sobre este código:

filename = "/my/directory/filename.txt"
dir = os.path.dirname(filename)

Queremos evitar sobrescribir la función incorporada, dir. Además, filepath o tal vez fullfilepath es probablemente un nombre semántico mejor que filename, por lo que sería mejor escribirlo:

import os
filepath = '/my/directory/filename.txt'
directory = os.path.dirname(filepath)

Su objetivo final es abrir este archivo, inicialmente declara, para escribir, pero esencialmente se está acercando a este objetivo (basado en su código) de esta manera, que abre el archivo para lectura :

if not os.path.exists(directory):
    os.makedirs(directory)
f = file(filename)

Asumiendo apertura para la lectura

¿Por qué haría un directorio para un archivo que espera que esté allí y pueda leer?

Solo intenta abrir el archivo.

with open(filepath) as my_file:
    do_stuff(my_file)

Si el directorio o el archivo no está allí, obtendrá un IOError con un número de error asociado: errno.ENOENT señalará el número de error correcto independientemente de su plataforma. Puedes atraparlo si quieres, por ejemplo:

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

Asumiendo que estamos abriendo para escribir

Esto es probablemente lo que quieres.

En este caso, probablemente no enfrentamos ninguna condición de carrera. Así que haz lo que eras, pero ten en cuenta que para escribir, debes abrir con el modo w (o a para adjuntar). También es una mejor práctica de Python utilizar el administrador de contexto para abrir archivos.

import os
if not os.path.exists(directory):
    os.makedirs(directory)
with open(filepath, 'w') as my_file:
    do_stuff(my_file)

Sin embargo, supongamos que tenemos varios procesos de Python que intentan poner todos sus datos en el mismo directorio. Entonces podemos tener una disputa sobre la creación del directorio. En ese caso, es mejor ajustar la llamada makedirs en un bloque 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)
44
Aaron Hall 1 abr. 2016 a las 21:54

Puede usar mkpath

# Create a directory and any missing ancestor directories. 
# If the directory already exists, do nothing.

from distutils.dir_util import mkpath
mkpath("test")    

Tenga en cuenta que también creará los directorios ancestrales.

Funciona para Python 2 y 3.

9
Dennis Golomazov 13 sep. 2016 a las 21:44

Usando 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 elimina todos los permisos, obtendrá un OSError elevado con errno.EACCES (Permiso denegado, error 13).

602
vallentin 24 abr. 2017 a las 01:55

Marque os.makedirs: (Se asegura de que se complete el camino existe.)
Para manejar el hecho de que el directorio podría existir, captura OSError. (Si exist_ok es False (el valor predeterminado), se genera un OSError si el directorio de destino ya existe).

import os
try:
    os.makedirs('./path/to/somewhere')
except OSError:
    pass
78
Georgy 16 may. 2019 a las 12:15

Yo uso os.path.exists(), aquí es un script de Python 3 que se puede usar para verificar si existe un directorio, cree uno si no existe y elimínelo si existe (si lo desea).

Solicita a los usuarios la entrada del directorio y puede modificarse fácilmente.

8
Peter Mortensen 31 dic. 2017 a las 03:16

Para una solución de una línea, puede usar IPython.utils.path.ensure_dir_exists():

from IPython.utils.path import ensure_dir_exists
ensure_dir_exists(dir)

De la documentación: Asegúrese de que exista un directorio. Si no existe, intente crearlo y protegerse contra una condición de carrera si otro proceso está haciendo lo mismo.

11
Georgy 16 may. 2019 a las 12:25

Encontré este Q / A y al principio me sorprendieron algunas de las fallas y errores que estaba recibiendo. Estoy trabajando en Python 3 (v.3.5 en un entorno virtual de Anaconda en un sistema Arch Linux x86_64).

Considere esta estructura de directorio:

└── output/         ## dir
   ├── corpus       ## file
   ├── corpus2/     ## dir
   └── subdir/      ## dir

Aquí están mis experimentos / notas, que aclaran las cosas:

# ----------------------------------------------------------------------------
# [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
# ----------------------------------------------------------------------------

Conclusión: en mi opinión, el "Método 2" es más robusto.

[1] ¿Cómo puedo crear un directorio si no existe?

[2] https://docs.python.org/3/library/ os.html # os.makedirs

6
Victoria Stuart 16 dic. 2017 a las 19:26

He puesto lo siguiente abajo. Sin embargo, no es totalmente infalible.

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

Ahora, como digo, esto no es realmente infalible, porque tenemos la posibilidad de no poder crear el directorio, y otro proceso de creación durante ese período.

29
Peter Mortensen 31 may. 2014 a las 14:05

A partir de Python 3.5, pathlib.Path.mkdir ha una bandera 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)

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

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

69
Viliami 17 dic. 2018 a las 07:05

Llame a la función create_dir() en el punto de entrada de su programa / proyecto.

import os

def create_dir(directory):
    if not os.path.exists(directory):
        print('Creating Directory '+directory)
        os.makedirs(directory)

create_dir('Project directory')
3
Steffi Keran Rani J 28 abr. 2018 a las 16:00
273192