“Error: [Errno 17] El archivo existe” al intentar usar os.makedirs [duplicate]

3 minutos de lectura

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.

  • 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

Avatar de usuario de Jahid
Jahid

A partir de Python >=3.2, os.makedirs() puede tomar un tercer argumento opcional exist_ok:

os.makedirs(mydir, exist_ok=True)

Avatar de usuario de John La Rooy
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ámetro os.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)

¿Ha sido útil esta solución?