Tengo varios subprocesos que se ejecutan en paralelo desde Python en un sistema de clúster. Cada hilo de python sale a un directorio mydir
. Cada secuencia de comandos, antes de la salida, comprueba si midir existe y si no lo crea:
if not os.path.isdir(mydir):
os.makedirs(mydir)
pero esto produce el error:
os.makedirs(self.log_dir)
File "/usr/lib/python2.6/os.py", line 157, in makedirs
mkdir(name,mode)
OSError: [Errno 17] File exists
Sospecho que podría deberse a una condición de carrera, donde un trabajo crea el directorio antes de que el otro llegue a ella. es posible? Si es así, ¿cómo se puede evitar este error?
No estoy seguro de que sea una condición de carrera, así que me preguntaba si otros problemas en Python pueden causar este extraño error.
Jahid
A partir de Python >=3.2
, os.makedirs()
puede tomar un tercer argumento opcional exist_ok
:
os.makedirs(mydir, exist_ok=True)
Juan La Rooy
En cualquier momento en que el código pueda ejecutarse entre el momento en que verifica algo y el momento en que actúa en consecuencia, tendrá una condición de carrera. Una forma de evitar esto (y la forma habitual en Python) es simplemente intentar y luego manejar la excepción
while True:
mydir = next_dir_name()
try:
os.makedirs(mydir)
break
except OSError, e:
if e.errno != errno.EEXIST:
raise
# time.sleep might help here
pass
Si tiene muchos subprocesos que intentan crear una serie predecible de directorios, aún generará muchas excepciones, pero al final llegará allí. Es mejor tener solo un hilo creando los directorios en ese caso
-
¿Por qué tienes el
break
¿ahí? Ese ciclo solo creará un directorio.–Ethan Furman
27/10/2015 a las 16:59
-
No ¡usa constantes codificadas! Usar
errno.EEXIST
en lugar de número mágico (17
). Si desea una solución más elegante para su problema, consulte la respuesta de @Jahid.– patryk.beza
26 de julio de 2017 a las 9:18
-
@patryk.beza, gracias. La respuesta de Jahid sería la mejor manera para la mayoría de las personas en estos días.
– John LaRooy
26/07/2017 a las 23:30
Captura la excepción y, si el errno es 17, ignóralo. Eso es lo único que puede hacer si hay una condición de carrera entre el isdir
y makedirs
llamadas
Sin embargo, también podría ser posible que un archivo con el mismo nombre existe – en ese caso os.path.exists
volvería True
pero os.path.isdir
devuelve falso.
-
¿Qué pasa con el uso
exist_ok
parámetroos.makedirs
a partir de Python 3.2? (Lo pregunto porque nunca lo he usado).– ovgolovin
17/09/2012 a las 22:44
-
@ovgolovin, parece que eso funcionaría bien, pero no muchos de nosotros somos compatibles con 3.2 todavía 🙂
– John LaRooy
17/09/2012 a las 22:51
Tuve problemas similares y esto es lo que hice
try:
if not os.path.exists(os.path.dirname(mydir)):
os.makedirs(os.path.dirname(mydir))
except OSError as err:
print(err)
Descripción:
Solo comprobando si el directorio ya existe arroja este mensaje de error [Errno 17] El archivo existe
porque solo estamos comprobando si el nombre del directorio existe o no, que devolverá el nombre del directorio del midir valor que se pasa, pero no si ya existe o no. Lo que se está perdiendo es no verificar si ese directorio ya existe, lo que se puede hacer verificando la ruta con os.ruta.existe() y ahí pasamos el nombre del directorio respectivo.
Para ignorar el error de existencia de archivo o directorio, puede intentar esto:
except OSError, e:
if e.errno != 17:
print("Error:", e)
Para aquellos que están atascados con el código heredado, consulte también Cómo solucionarlo
exist_ok
falta en Python 2.7?.– Karl Knechtel
15 de marzo a las 5:37