Menu

Comprobar si un archivo existe en Python: os.path, pathlib y try/except

Tres formas de comprobar si un archivo existe en Python: os.path.exists e isfile, Path.exists e is_file de pathlib, y abrir el archivo dentro de try/except FileNotFoundError.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

La respuesta corta

Para comprobar si un archivo existe, usa os.path.isfile() de la biblioteca estándar. Devuelve True cuando la ruta nombra un archivo regular que existe y False en caso contrario. Nunca lanza un error por una ruta que no existe.

Las rutas son relativas a la carpeta desde la que se ejecuta el programa (el directorio de trabajo actual), salvo que pases una ruta absoluta como /home/ada/notes.txt o C:\Users\Ada\notes.txt.

El resto de esta página cubre las otras formas de hacer la pregunta, en qué se diferencian y el caso en que no deberías hacerla.

os.path.exists vs isfile vs isdir

El módulo os.path tiene tres comprobaciones relacionadas, y responden a preguntas ligeramente distintas:

FunciónDevuelve True cuando la ruta es
os.path.exists(p)cualquier cosa que exista: un archivo, un directorio o un enlace simbólico válido
os.path.isfile(p)un archivo regular que existe
os.path.isdir(p)un directorio que existe

La diferencia aparece en cuanto hay un directorio de por medio:

Salida:

reports True False True
reports/summary.txt True True False
reports/old.txt False False False

os.path.exists("reports") es True aunque reports sea una carpeta. Si tu código va a leer la ruta como un archivo, exists es la comprobación equivocada: un directorio la pasaría, y luego open("reports") fallaría (con IsADirectoryError en Linux y macOS, PermissionError en Windows). Elige isfile cuando te refieras a un archivo e isdir cuando te refieras a una carpeta.

Dos detalles más sobre estas tres funciones de os.path:

  • Los enlaces simbólicos se siguen. Un enlace que apunta a un archivo real cuenta como archivo; un enlace roto (su destino ya no existe) devuelve False en las tres.
  • Si Python no tiene permiso para mirar dentro de una carpeta, la comprobación devuelve False en lugar de lanzar PermissionError. False significa "no encontrado o no accesible", no estrictamente "no existe".

Comprobarlo con pathlib

pathlib es la API orientada a objetos para rutas de la biblioteca estándar, y la mayoría del código nuevo la usa. Un objeto Path tiene las mismas tres comprobaciones como métodos:

Path.exists(), Path.is_file() y Path.is_dir() se comportan como os.path.exists, isfile e isdir. El operador / une partes de una ruta con el separador correcto para el sistema operativo, así que folder / "summary.txt" funciona igual en Windows, macOS y Linux. Consulta manejo de archivos para leer y escribir a través de objetos Path.

¿Cuál deberías usar? Si el resto de tu código ya pasa objetos Path de un lado a otro, quédate con pathlib. Si trabajas con strings normales y funciones de os, os.path.isfile es igual de correcto. Dan las mismas respuestas.

Por qué comprobar primero puede ser un error

La razón más común para comprobar si un archivo existe es abrirlo después:

import os

if os.path.isfile("config.txt"):
    with open("config.txt") as f:      # puede que el archivo ya no esté
        settings = f.read()
else:
    settings = ""

Esto tiene un hueco. Entre la llamada a isfile() y la llamada a open(), otro programa, otro hilo o el propio usuario pueden borrar o renombrar el archivo. La comprobación dijo True, la apertura falla igualmente y tu programa se detiene con FileNotFoundError de todos modos. Ese hueco se llama condición de carrera, o "time of check to time of use" (del momento de la comprobación al momento del uso). Es raro en tu propio portátil y bastante menos raro en un servidor con mucha carga donde varios procesos comparten una carpeta.

La solución es saltarse la comprobación aparte y dejar que open() sea la comprobación. Python lanza FileNotFoundError cuando falta el archivo, y tú lo manejas en except:

Salida:

theme=dark
(no settings file, using defaults)

Ahora hay una sola operación en lugar de dos, así que no hay carrera posible. Este estilo tiene nombre en la comunidad de Python: EAFP, "easier to ask forgiveness than permission" (es más fácil pedir perdón que permiso). El estilo contrario, comprobar primero, es LBYL, "look before you leap" (mira antes de saltar). Python se inclina por EAFP al trabajar con archivos porque el sistema operativo es lo único que conoce la respuesta en el momento en que abres el archivo.

FileNotFoundError no es lo único que puede salir mal. Una ruta que es un directorio lanza IsADirectoryError (PermissionError en Windows), y un archivo que no puedes leer lanza PermissionError. Las tres son subclases de OSError, así que except OSError: captura de una vez todos los casos de "no se pudo abrir". La página de excepciones explica cómo elegir entre capturar un error concreto y capturar una familia.

Cuándo una comprobación simple está bien

Comprobar primero no está mal en todos los casos. Es la herramienta adecuada cuando solo necesitas la respuesta y no vas a actuar sobre el archivo en la línea siguiente:

  • elegir qué mensaje mostrar ("Found 3 saved games")
  • validar una ruta que escribió el usuario antes de empezar un trabajo largo
  • saltarse trabajo que ya se hizo, donde una respuesta desactualizada solo cuesta repetirlo

La regla general: si vas a abrir, leer, escribir o borrar el archivo, hazlo dentro de try. Si solo quieres saberlo, isfile() o Path.is_file() está bien.

Crear un archivo solo si no existe

También surge la pregunta inversa: "escribe este archivo, pero nunca sobrescribas uno que ya exista". La versión obvia tiene la misma carrera que antes:

if not os.path.exists("report.txt"):
    with open("report.txt", "w") as f:   # otro proceso puede crearlo primero
        f.write("new report\n")

El modo "x" (creación exclusiva) hace ambos pasos en uno. Crea el archivo, o lanza FileExistsError si el nombre ya está ocupado:

Salida:

attempt 1: created report.txt
attempt 2: report.txt already exists, left it alone

Para carpetas, os.makedirs(path, exist_ok=True) y Path(path).mkdir(parents=True, exist_ok=True) crean el directorio y cualquier directorio padre que falte, y no hacen nada si ya existe. No hace falta llamar antes a isdir().

Errores comunes

  • Usar exists() cuando te refieres a un archivo. Un directorio con el mismo nombre pasa la comprobación. Usa isfile() o Path.is_file().
  • Olvidar desde dónde empiezan las rutas relativas. "data.txt" se busca en el directorio de trabajo actual, que es desde donde lanzaste el programa, no necesariamente la carpeta que contiene el script. Para encontrar un archivo junto al script, construye la ruta a partir de Path(__file__).parent.
  • Comprobar y después abrir. El archivo puede cambiar entre medias. Ábrelo dentro de try y maneja FileNotFoundError.
  • Capturar cualquier excepción. except Exception: alrededor de open() también oculta erratas y bugs en el código que lee el archivo. Captura FileNotFoundError u OSError.

Preguntas frecuentes

¿Cómo compruebo si un archivo existe en Python?

Importa os y llama a os.path.isfile("data.txt"), que devuelve True solo para un archivo regular que existe. Con pathlib es Path("data.txt").is_file(). Usa os.path.exists() o Path.exists() cuando también deba contar un directorio con ese nombre.

¿Cuál es la diferencia entre os.path.exists y os.path.isfile?

os.path.exists(p) es True para cualquier cosa en esa ruta: un archivo, un directorio o un enlace simbólico que apunta a algo real. os.path.isfile(p) es True solo para un archivo regular, así que devuelve False para un directorio. os.path.isdir(p) es su equivalente para directorios.

¿Debo comprobar si un archivo existe antes de abrirlo?

Normalmente no. El archivo puede borrarse o crearse entre la comprobación y la llamada a open(), así que la comprobación no garantiza nada. Abre el archivo directamente dentro de try y maneja FileNotFoundError en except. Una comprobación aparte es lo correcto cuando solo necesitas la respuesta, por ejemplo para decidir qué mensaje mostrar.

¿Cómo creo un archivo solo si no existe?

Ábrelo con el modo "x": open("report.txt", "x"). Python crea el archivo, o lanza FileExistsError si ya hay algo con ese nombre. La comprobación y la creación ocurren en un solo paso, así que ningún otro programa puede colarse entre ambas.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR