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.
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.exists
y 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.exists
pero 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 regresaTrue
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 aos.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 utilizaos.mkdir()
estos errores generarán una excepción, alertándolo de su existencia.– drevicko
6 de julio de 2013 a las 6:41
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 pathlib
le 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 exists
es 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
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
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()
.
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
bufón
Prueba el os.path.exists
función
if not os.path.exists(dir):
os.mkdir(dir)
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
p
aquí 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