example - os.system() python
¿Cómo puedo crear de forma segura un directorio anidado en Python? (25)
¿Comprobar si existe un directorio y crearlo si es necesario?
La respuesta directa a esto es, asumiendo una situación simple en la que no espera que otros usuarios o procesos se metan con su directorio:
if not os.path.exists(d):
os.makedirs(d)
o si hacer el directorio está sujeto a condiciones de carrera (es decir, si después de verificar que existe la ruta, es posible que otra cosa ya lo haya hecho):
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 la contención de recursos, mediante el uso de directorios temporales a través de tempfile
:
import tempfile
d = tempfile.mkdtemp()
Aquí está lo esencial 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.
Nuevo 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 querría usar con path, uno de los cuales es mkdir
.
(Para el contexto, estoy siguiendo a mi representante semanal con una secuencia de comandos. Aquí están las partes relevantes del código de la secuencia de comandos que me permiten evitar el desbordamiento de pila más de una vez al día por la misma información).
Primero las importaciones relevantes:
from pathlib import Path
import tempfile
No tenemos que lidiar con os.path.join
ahora - simplemente unir partes de ruta con un /
:
directory = Path(tempfile.gettempdir()) / ''sodata''
Luego, me aseguro de que el directorio exista, el argumento exist_ok
muestra en Python 3.5:
directory.mkdir(exist_ok=True)
Aquí está la parte relevante de la pathlib.Path.mkdir :
Si
exist_ok
es verdadero, se ignorarán las excepcionesFileExistsError
(el mismo comportamiento que el comandoPOSIX mkdir -p
), pero solo si el último componente de la ruta no es un archivo que no sea de directorio.
Aquí hay un poco más del guión: en mi caso, no estoy sujeto a una condición de carrera, solo tengo un proceso que espera que el directorio (o los archivos contenidos) esté allí, y no tengo nada que intentar 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))
Path
objetos de Path
deben ser forzados a str
antes de que otras API que esperan que las rutas str
puedan usarlos.
Quizás Pandas debería actualizarse para aceptar instancias de la clase base abstracta, os.PathLike
.
¿Cuál es la forma más elegante de verificar si existe el directorio en el que se va a escribir un archivo y, de no ser así, crear el directorio utilizando Python? Esto es lo que intenté:
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ñaba 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?
Perspectivas sobre los detalles de esta situación.
Usted da un archivo particular en una ruta determinada y saca el directorio de la ruta del archivo. Luego, después de asegurarse de que tiene 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 quizás fullfilepath
es probablemente un nombre semántico mejor que el nombre de filename
por lo que este debería escribirse mejor:
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á aproximando a este objetivo (basado en su código) de esta manera, lo que abre el archivo para su 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 estar allí y poder leer?
Solo intenta abrir el archivo.
with open(filepath) as my_file:
do_stuff(my_file)
Si el directorio o el archivo no están allí, obtendrá un error IOError
con un número de error asociado: errno.ENOENT
apuntará al 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
Suponiendo que estamos abriendo para escribir
Esto es probablemente lo que estás queriendo.
En este caso, probablemente no estamos enfrentando ninguna condición de carrera. Así que haz lo que fuiste, pero ten en cuenta que para escribir, debes abrir con el modo w
(o a
anexo). También es una práctica recomendada de Python usar 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 colocar todos sus datos en el mismo directorio. Entonces podremos tener disputa sobre la creación del directorio. En ese caso, es mejor envolver 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)
Python 3.5+:
import pathlib
pathlib.Path(''/my/directory'').mkdir(parents=True, exist_ok=True)
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 no quiere que se creen los parents
, omita el argumento de los parents
.
Python 3.2+:
Utilizando pathlib
:
Si puede, instale el backport de pathlib
actual llamado pathlib2
. No instale el backport no mantenido antiguo denominado pathlib
. A continuación, consulte la sección anterior de Python 3.5+ y úselo de la misma manera.
Si se usa Python 3.4, aunque viene con pathlib
, falta la útil opción exist_ok
. El objetivo de Backport es ofrecer una implementación más nueva y superior de mkdir
que incluya esta opción que falta.
Utilizando os
:
import os
os.makedirs(path, exist_ok=True)
os.makedirs
como se usa anteriormente crea recursivamente el directorio y no genera una excepción si el directorio ya existe. Tiene el argumento opcional exist_ok
solo si se 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 un manejo manual de excepciones como con Python 2.7.
Python 2.7+:
Utilizando pathlib
:
Si puede, instale el backport de pathlib
actual llamado pathlib2
. No instale el backport no mantenido antiguo denominado pathlib
. A continuación, consulte la sección anterior de Python 3.5+ y úselo de la misma manera.
Utilizando 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 elimina la ambigüedad de 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 errno.EEXIST
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.
import distutils.dir_util
distutils.dir_util.mkpath(path)
Según el error 10948 , una grave limitación 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á silenciosamente su información en caché no válida de haber creado previamente el directorio, y En realidad no volverá a hacer el directorio. En contraste, os.makedirs
no se basa en ningún tipo de caché. Esta limitación puede estar bien para algunas aplicaciones.
Con respecto al modo del directorio, consulte la documentación si le interesa.
¿Por qué no usar el módulo de subproceso si se ejecuta en una máquina que admite lenguajes de shell? 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.
A partir de Python 3.5, pathlib.Path.mkdir
tiene un indicador 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.
(al igual que os.makedirs
obtuvo un exists_ok
partir de python 3.2).
Compruebe os.makedirs : (Se asegura de que exista la ruta completa).
Para manejar el hecho de que el directorio pueda existir, capture OSError. (Si exist_ok es False (el valor predeterminado), se genera un error OSE si el directorio de destino ya existe).
import os
try:
os.makedirs(''./path/to/somewhere'')
except OSError:
pass
Cuando se trabaja con archivos de E / S, lo importante a considerar es
TOCTTOU (tiempo de verificación a tiempo de uso)
Por lo tanto, hacer una verificación con if
y luego leer o escribir más tarde puede terminar en una excepción de E / S no controlada. La mejor manera de hacerlo es:
try:
os.makedirs(dir_path)
except OSError as e:
if e.errno != errno.EEXIS:
raise
El uso de 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, cualquier otro error se reporta. Por ejemplo, si crea dir ''a'' de antemano y elimina todos los permisos, obtendrá un OSError
elevado con errno.EACCES
(Permiso denegado, error 13).
En Python3 , os.makedirs
admite la configuración de exist_ok
. La configuración predeterminada es False
, lo que significa que se OSError
un OSError
si el directorio de destino ya existe. Al establecer 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 de exist_ok
. Puedes usar el enfoque en la 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
En Python 3.4 también puedes 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.
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 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://.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] os.makedirs
He puesto lo siguiente abajo. Aunque 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 crear el directorio, y otro proceso lo está creando durante ese período.
La documentación relevante de Python sugiere el uso del estilo de codificación EAFP (más fácil de pedir perdón que el 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 lo mencionan aquí, hay 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 puede recomendarse en el caso especial de que el programa haya establecido un entorno privado para Sí (y otras instancias del mismo programa).
Incluso en ese caso, esta es una mala práctica y puede llevar a una depuración inútil por mucho tiempo. Por ejemplo, el hecho de que configuremos los permisos para un directorio no debe dejarnos con la impresión de que los permisos se configuran de manera adecuada para nuestros propósitos. Un directorio padre podría ser montado con otros permisos. En general, un programa siempre debe funcionar correctamente y el programador no debe esperar un entorno específico.
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'')
Para una solución de una sola línea, puede usar IPython.utils.path.ensure_dir_exists()
:
from IPython.utils.path import ensure_dir_exists
ensure_dir_exists(dir)
De la documentation : Asegúrese de que existe un directorio. Si no existe, intente crearlo y protegerlo contra una condición de carrera si otro proceso está haciendo lo mismo.
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 de usuario tonta:
:: /tmp/dirname/filename.etc
... Vas a terminar con un directorio llamado filename.etc
cuando pases ese argumento a os.makedirs()
si pruebas con os.path.exists()
.
Prueba la función os.path.exists
if not os.path.exists(dir):
os.mkdir(dir)
Puedes 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 de antepasados.
Funciona para Python 2 y 3.
Puedes usar os.listdir
para esto:
import os
if ''dirName'' in os.listdir(''parentFolderPath'')
print(''Directory Exists'')
Si consideras lo siguiente:
os.path.isdir(''/tmp/dirname'')
significa que un directorio (ruta) existe Y es un directorio. Así que para mí de esta manera hace lo que necesito. Así que puedo asegurarme de que sea una carpeta (no un archivo) y que exista.
Usa este comando chequea y crea dir.
if not os.path.isdir(test_img_dir):
os.mkdir(str("./"+test_img_dir))
Utilizo os.path.exists()
, here hay un script de Python 3 que se puede usar para verificar si existe un directorio, crear uno si no existe y eliminarlo si existe (si se desea).
Solicita a los usuarios la entrada del directorio y se puede modificar fácilmente.
Veo dos respuestas con buenas cualidades, cada una con un pequeño defecto, así que daré mi opinión sobre esto:
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 indicó en los comentarios y en otras partes, hay una condición de carrera: si el directorio se crea entre os.path.exists
y las llamadas os.makedirs
, os.makedirs
fallará con un OSError
. Desafortunadamente, la captura de OSError
y la continuación no son infalibles, ya que ignorará un error al crear el directorio debido a otros factores, como permisos insuficientes, disco completo, etc.
Una opción sería interceptar el OSError
y examinar el código de error incorporado (ver ¿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 existir un segundo os.path.exists
, pero supongamos que otro haya creado el directorio después de la primera comprobación y luego lo haya eliminado antes de la segunda: aún podríamos dejarnos engañar.
Dependiendo de la aplicación, el peligro de operaciones concurrentes puede ser mayor o menor que el peligro planteado por 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.
Vi las respuestas de Heikki Toivonen y share y pensé en esta variación.
import os
import errno
def make_sure_path_exists(path):
try:
os.makedirs(path)
except OSError as exception:
if exception.errno != errno.EEXIST or not os.path.isdir(path):
raise
import os
if os.path.isfile(filename):
print "file exists"
else:
"Your code here"
Donde su código aquí es use el comando (toque)
Esto comprobará si el archivo está allí, si no lo está, entonces lo creará.