¿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, extrañé 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?
os.path.mkdir
no existe. Esos.mkdir
.p
, aquí está mi fragmento de código:os.makedirs(p[:p.rindex(os.path.sep)], exist_ok=True)
Respuestas:
En Python ≥ 3.5, use
pathlib.Path.mkdir
:Para 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:
Prueba
os.path.exists
y consideraos.makedirs
para la creación.Como se señaló en los comentarios y en otros lugares, hay una condición de carrera: si el directorio se crea entre
os.path.exists
y lasos.makedirs
llamadas,os.makedirs
fallará con unOSError
. Desafortunadamente, la cobijaOSError
y la continuación no son infalibles, ya que ignorará una falla al crear el directorio debido a otros factores, como permisos insuficientes, disco completo, etc.Una opción sería atrapar
OSError
y examinar el código de error incrustado (consulte ¿Hay una manera multiplataforma de obtener información del OSError de Python? ):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 las 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
FileExistsError
(en 3.3+) ...... y al permitir que un argumento de palabra clave que
os.makedirs
se llamaexist_ok
(en 3.2+).fuente
os.path.exists
También vuelveTrue
para un archivo. He publicado una respuesta para abordar esto.exists_ok
parámetro aos.makedirs()
se puede usar para cubrir cómo se maneja la existencia previa de la ruta, desde Python 3.2.os.mkdirs()
puede crear carpetas no deseadas si se omite accidentalmente un separador de ruta, la carpeta actual no es la esperada, un elemento de ruta contiene el separador de ruta. Si usaos.mkdir()
estos errores, se generará una excepción y le alertará sobre su existencia.Python 3.5+:
pathlib.Path.mkdir
como se usa anteriormente, crea recursivamente el directorio y no genera una excepción si el directorio ya existe. Si no necesita o desea que se creen los padres, omita elparents
argumento.Python 3.2+:
Utilizando
pathlib
:Si puede, instale el
pathlib
puerto actual llamadopathlib2
. No instale el backport sin mantenimiento anterior llamadopathlib
. 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 laexist_ok
opción útil . El backport está destinado a ofrecer una implementación más nueva y superiormkdir
que incluye esta opción que falta.Utilizando
os
:os.makedirs
como se usa anteriormente, crea recursivamente el directorio y no genera una excepción si el directorio ya existe. Tiene elexist_ok
argumento opcional solo si usa Python 3.2+, con un valor predeterminado deFalse
. 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+:
Utilizando
pathlib
:Si puede, instale el
pathlib
puerto actual llamadopathlib2
. No instale el backport sin mantenimiento anterior llamadopathlib
. A continuación, consulte la sección Python 3.5+ anterior y úsela igual.Utilizando
os
:Mientras que una solución ingenua puede usarse primero,
os.path.isdir
seguida poros.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 usarlo
errno
es de utilidad limitada porqueOSError: [Errno 17] File exists
, es decirerrno.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.Según el error 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
mkpath
vuelva a usarlo 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 lo hará. Realmente hacer el directorio de nuevo. 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.
fuente
os.path.isdir
otra persona elimine la carpeta, generará el error incorrecto, desactualizado y confuso de que esa carpeta existe.Usando try except y el código de error correcto del módulo errno elimina la condición de carrera y es multiplataforma:
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
aumento conerrno.EACCES
(Permiso denegado, error 13).fuente
exception.errno != errno.EEXIST
ignore involuntariamente el caso cuando la ruta existe pero es un objeto que no es un directorio, como un archivo. La excepción idealmente debería plantearse si la ruta es un objeto que no es de directorio.os.makedirs(path,exist_ok=True)
exist_ok
parámetro se introdujo en Python 3.2. No está presente en Python 2.x. Lo incorporaré en mi respuesta.Yo personalmente recomendaría que utilices
os.path.isdir()
para probar en lugar deos.path.exists()
.Si usted tiene:
Y una entrada tonta del usuario:
... Vas a terminar con un directorio llamado
filename.etc
cuando pasas ese argumentoos.makedirs()
si pruebas conos.path.exists()
.fuente
Verifique
os.makedirs
: (Se asegura de que exista la ruta completa).Para manejar el hecho de que el directorio podría existir, capture
OSError
. (Siexist_ok
esFalse
(el valor predeterminado),OSError
se genera un si el directorio de destino ya existe).fuente
OSError
aparecerá aquí si la ruta es un archivo o directorio existente. He publicado una respuesta para abordar esto.OSError
antes de decidir ignorarlo. Ver stackoverflow.com/a/5032238/763269 .A partir de Python 3.5,
pathlib.Path.mkdir
tiene unaexist_ok
bandera:Esto crea recursivamente el directorio y no genera una excepción si el directorio ya existe.
(así como
os.makedirs
obtuve unaexist_ok
bandera a partir de Python 3.2, por ejemploos.makedirs(path, exist_ok=True)
)fuente
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:
Queremos evitar la sobreescritura de la función interna,
dir
. Además,filepath
o tal vezfullfilepath
sea probablemente un nombre semántico mejor quefilename
este, así estaría mejor escrito: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 leer :
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.
Si el directorio o el archivo no está allí, obtendrá un
IOError
número de error asociado:errno.ENOENT
apuntará al número de error correcto independientemente de su plataforma. Puedes atraparlo si quieres, por ejemplo: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
w
modo (oa
agregar). También es una mejor práctica de Python utilizar el administrador de contexto para abrir archivos.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 envolver la
makedirs
llamada en un bloque try-except.fuente
Prueba la
os.path.exists
funciónfuente
os.path.mkdir()
método El módulo os.path implementa algunas funciones útiles en los nombres de ruta .He puesto lo siguiente abajo. Sin embargo, no es totalmente infalible.
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.
fuente
os.path.exists
, consulte stackoverflow.com/a/5032238/763269, y (2) el éxitoos.path.exists
no significa que el directorio existe, solo que la ruta existe: podría ser un archivo, un enlace simbólico u otro objeto del sistema de archivos.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:
o si hacer el directorio está sujeto a condiciones de carrera (es decir, si después de verificar que la ruta existe, es posible que ya haya hecho algo más) haga esto:
Pero quizás un enfoque aún mejor es eludir el problema de contención de recursos, utilizando directorios temporales a través de
tempfile
:Aquí están los elementos esenciales del documento en línea:
Nuevo en Python 3.5:
pathlib.Path
conexist_ok
Hay un nuevo
Path
objeto (a partir de 3.4) con muchos métodos que uno desearía usar con rutas, uno de los cuales esmkdir
.(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:
No tenemos que lidiar
os.path.join
ahora, solo une las partes del camino con/
:Luego, me aseguro de que el directorio exista, el
exist_ok
argumento se muestra en Python 3.5:Aquí está la parte relevante de la documentación :
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.
Path
los objetos deben ser forzadosstr
antes de que otras API que esperanstr
rutas puedan usarlos.Tal vez pandas debe actualizarse para aceptar instancias de la clase base abstracta,
os.PathLike
.fuente
En Python 3.4 también puede usar el nuevo
pathlib
módulo :fuente
pathlib
y dóndepathlib2
para los nuevos usuarios, y creo que los profesionales aquí descubrirán la depreciación;)La documentación relevante de Python sugiere el uso del estilo de codificación EAFP (más fácil pedir perdón que permiso) . Esto significa que el código
es mejor que la alternativa
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.
fuente
En Python3 ,
os.makedirs
admite la configuraciónexist_ok
. La configuración predeterminada esFalse
, lo que significaOSError
que se generará un si el directorio de destino ya existe. Al establecerexist_ok
enTrue
,OSError
(el directorio existe) se ignorará y el directorio no se creará.En Python2 ,
os.makedirs
no admite la configuraciónexist_ok
. Puede usar el enfoque en la respuesta de heikki-toivonen :fuente
Para una solución de una línea, puede usar
IPython.utils.path.ensure_dir_exists()
: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.
fuente
IPython
módulo de ninguna manera está garantizado para estar presente. Está presente de forma nativa en mi Mac, pero no en ninguna de mis instalaciones de Linux de Python. Básicamente, no es uno de los módulos enumerados en el índice del módulo Python .pip install ipython
o incluir la dependencia en su requirements.txt o pom.xml . Documentación: ipython.org/install.htmlPuedes usar
mkpath
Tenga en cuenta que también creará los directorios ancestrales.
Funciona para Python 2 y 3.
fuente
distutils.dir_util
no forma parte de la API pública distutil y tiene problemas en entornos de subprocesos múltiples: bugs.python.org/issue10948distutils.dir_util.mkpath
es que si crea un directorio, luego lo elimina de dentro o fuera de Python, luegomkpath
vuelva a usarlo ,mkpath
simplemente usará su información en caché no válida de haber creado previamente el directorio, y En realidad, no hacer el directorio de nuevo. Por el contrario,os.makedirs
no se basa en tal caché.Yo uso
os.path.exists()
, aquí hay un script de Python 3 que puede usarse para verificar si existe un directorio, crear uno si no existe y eliminarlo si existe (si lo desea).Solicita a los usuarios la entrada del directorio y puede modificarse fácilmente.
fuente
Puedes usar
os.listdir
para esto:fuente
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:
Aquí están mis experimentos / notas, que aclaran las cosas:
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
fuente
Vi las respuestas de Heikki Toivonen y ABB y pensé en esta variación.
fuente
Use este comando check y cree dir
fuente
¿Por qué no usar el módulo de subproceso si se ejecuta en una máquina que admite comandos
mkdir
con-p
opción? Funciona en python 2.7 y python 3.6Deberí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:
fuente
Si considera lo siguiente:
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.
fuente
Llame a la función
create_dir()
en el punto de entrada de su programa / proyecto.fuente
Debe establecer la ruta completa antes de crear el directorio:
Esto funciona para mí y, con suerte, también funcionará para ti
fuente
Esto verificará si el archivo está allí, si no lo está, lo creará.
fuente