¿Cómo verifico si existe un archivo sin excepciones?


Respuestas:


5155

Si la razón por la que está verificando es para que pueda hacer algo como if file_exists: open_it(), es más seguro usar un tryintento de abrirlo. Verificar y luego abrir se arriesga a que el archivo se elimine o se mueva o algo entre cuando lo verifique y cuando intente abrirlo.

Si no planea abrir el archivo de inmediato, puede usar os.path.isfile

Devuelve Truesi la ruta es un archivo regular existente. Esto sigue los enlaces simbólicos, por lo que tanto islink () como isfile () pueden ser verdaderos para la misma ruta.

import os.path
os.path.isfile(fname) 

si necesita estar seguro de que es un archivo

Comenzando con Python 3.4, el pathlibmódulo ofrece un enfoque orientado a objetos (respaldado pathlib2en Python 2.7):

from pathlib import Path

my_file = Path("/path/to/file")
if my_file.is_file():
    # file exists

Para verificar un directorio, haga:

if my_file.is_dir():
    # directory exists

Para verificar si un Pathobjeto existe independientemente de si es un archivo o directorio, use exists():

if my_file.exists():
    # path exists

También puedes usar resolve(strict=True)en un trybloque:

try:
    my_abs_path = my_file.resolve(strict=True)
except FileNotFoundError:
    # doesn't exist
else:
    # exists

40
con respecto a la primera observación (use "probar" si marca antes de abrir) desafortunadamente esto no funcionará si desea abrir para agregar, asegurándose de que existe antes ya que el modo 'a' creará si no existe.
makapuf

66
Tenga en cuenta que FileNotFoundErrorse introdujo en Python 3. Si también necesita admitir Python 2.7 y Python 3, puede usar IOErroren su lugar (qué FileNotFoundErrorsubclases) stackoverflow.com/a/21368457/1960959
scottclowe

77
@makapuf Puede abrirlo para "actualizar" ( open('file', 'r+')) y luego buscar hasta el final.
kyrill el

2111

Tienes la os.path.existsfunción:

import os.path
os.path.exists(file_path)

Esto devuelve Truetanto para archivos como para directorios, pero en su lugar puede usar

os.path.isfile(file_path)

para probar si es un archivo específicamente. Sigue los enlaces simbólicos.


966

A diferencia isfile(), exists()volverá Truepara los directorios. Entonces, dependiendo de si solo desea archivos simples o también directorios, usará isfile()o exists(). Aquí hay una salida REPL simple:

>>> os.path.isfile("/etc/password.txt")
True
>>> os.path.isfile("/etc")
False
>>> os.path.isfile("/does/not/exist")
False
>>> os.path.exists("/etc/password.txt")
True
>>> os.path.exists("/etc")
True
>>> os.path.exists("/does/not/exist")
False

623
import os.path

if os.path.isfile(filepath):

320

Usar os.path.isfile()con os.access():

import os

PATH = './file.txt'
if os.path.isfile(PATH) and os.access(PATH, os.R_OK):
    print("File exists and is readable")
else:
    print("Either the file is missing or not readable")

6060
Tener múltiples condiciones, algunas de las cuales son superfluas, es menos claro y explícito.
wim

10
También es redundante. Si el archivo no existe, os.access()devolverá falso.
Marqués de Lorne

99
@EJP En Linux los archivos pueden existir pero no son accesibles.
e-info128

8
ya que import osusted no necesita import os.pathvolver a hacerlo, ya que ya forma parte de él os. Solo necesita importar os.pathsi solo va a usar funciones de os.pathy no de ossí mismo, para importar algo más pequeño, pero a medida que usa os.accessy os.R_OK, la segunda importación no es necesaria.
Bufón

287
import os
os.path.exists(path) # Returns whether the path (directory or file) exists or not
os.path.isfile(path) # Returns whether the file exists or not

2
En general, no es una buena práctica nombrar variables de la misma manera que los nombres de métodos.
Homunculus Reticulli

245

Aunque casi todas las formas posibles se han enumerado en (al menos una de) las respuestas existentes (por ejemplo, se agregaron cosas específicas de Python 3.4 ), intentaré agrupar todo.

Nota : cada parte del código de la biblioteca estándar de Python que voy a publicar pertenece a la versión 3.5.3 .

Declaración del problema :

  1. Comprobar existencia de archivo ( discutible : también carpeta (archivo "especial"))
  2. No use los bloques try / except / else / finally

Posibles soluciones :

  1. [Python 3]: os.path. que existe ( ruta ) (también comprobar otros miembros de la familia como función os.path.isfile, os.path.isdir, os.path.lexistsde comportamientos ligeramente diferentes)

    os.path.exists(path)

    Devuelve Truesi la ruta se refiere a una ruta existente o un descriptor de archivo abierto. Devoluciones Falsepor enlaces simbólicos rotos. En algunas plataformas, esta función puede regresar Falsesi no se otorga permiso para ejecutar os.stat () en el archivo solicitado, incluso si la ruta existe físicamente.

    Todo bien, pero si sigue el árbol de importación:

    • os.path- posixpath.py ( ntpath.py )

      • genericpath.py , línea ~ # 20 +

        def exists(path):
            """Test whether a path exists.  Returns False for broken symbolic links"""
            try:
                st = os.stat(path)
            except os.error:
                return False
            return True

    es solo un bloque try / except alrededor de [Python 3]: os. stat ( ruta, *, dir_fd = Ninguno, follow_symlinks = Verdadero ) . Entonces, su código es try / except free, pero más abajo en el stackstack hay (al menos) uno de esos bloques. Esto también se aplica a otros funcs ( incluidos os.path.isfile ).

    1.1. [Python 3]: Camino. is_file ()

    • Es una forma más elegante (y más python ic) de manejar rutas, pero
    • Debajo del capó, hace exactamente lo mismo ( pathlib.py , línea ~ # 1330 ):

      def is_file(self):
          """
          Whether this path is a regular file (also True for symlinks pointing
          to regular files).
          """
          try:
              return S_ISREG(self.stat().st_mode)
          except OSError as e:
              if e.errno not in (ENOENT, ENOTDIR):
                  raise
              # Path doesn't exist or is a broken symlink
              # (see https://bitbucket.org/pitrou/pathlib/issue/12/)
              return False
  2. [Python 3]: con gestores de contexto de declaración . Ya sea:

    • Crea uno:

      class Swallow:  # Dummy example
          swallowed_exceptions = (FileNotFoundError,)
      
          def __enter__(self):
              print("Entering...")
      
          def __exit__(self, exc_type, exc_value, exc_traceback):
              print("Exiting:", exc_type, exc_value, exc_traceback)
              return exc_type in Swallow.swallowed_exceptions  # only swallow FileNotFoundError (not e.g. TypeError - if the user passes a wrong argument like None or float or ...)
      • Y su uso: replicaré el os.path.isfilecomportamiento (tenga en cuenta que esto es solo para fines de demostración, no intente escribir dicho código para la producción ):

        import os
        import stat
        
        
        def isfile_seaman(path):  # Dummy func
            result = False
            with Swallow():
                result = stat.S_ISREG(os.stat(path).st_mode)
            return result
    • Utilice [Python 3]: contextlib. suprimir ( * excepciones ) - que fue diseñado específicamente para suprimir selectivamente excepciones


    Pero, parecen ser envoltorios sobre bloques try / except / else / finally , como [Python 3]: La declaración with dice:

    Esto permite un intento común ... excepto ... finalmente, los patrones de uso se encapsulan para una reutilización conveniente.

  3. Funciones transversales del sistema de archivos (y busque los resultados para elementos coincidentes)


    Dado que estos iteran sobre las carpetas (en la mayoría de los casos) son ineficientes para nuestro problema (hay excepciones, como el bing de globo no comodín , como señaló @ShadowRanger), por lo que no voy a insistir en ellos. Sin mencionar que en algunos casos, el procesamiento del nombre de archivo puede ser requerido.

  4. [Python 3]: os. de acceso ( path, el modo, *, dir_fd = ninguno, effective_ids = False, follow_symlinks = true ) cuyo comportamiento está cerca os.path.exists(en realidad es más amplia, principalmente debido a la 2 ª argumento)

    • los permisos de usuario pueden restringir la "visibilidad" del archivo como dice el documento:

      ... prueba si el usuario que invoca tiene el acceso especificado a la ruta . el modo debe ser F_OK para probar la existencia de ruta ...

    os.access("/tmp", os.F_OK)

    Desde También trabajo en C , utilizo este método, así porque bajo el capó, llama a nativo API s (de nuevo, a través de "$ {} PYTHON_SRC_DIR /Modules/posixmodule.c" ), pero también abre una puerta para un posible usuario errores , y no es tan Python ic como otras variantes. Entonces, como señaló correctamente @AaronHall, no lo use a menos que sepa lo que está haciendo:

    Nota : también es posible llamar a API s nativas a través de [Python 3]: ctypes : una biblioteca de funciones foráneas para Python , pero en la mayoría de los casos es más complicada.

    ( Win específico): dado que vcruntime * ( msvcr * ) .dll exporta una [MS.Docs]: _access, _waccess function family también, aquí hay un ejemplo:

    Python 3.5.3 (v3.5.3:1880cb95a742, Jan 16 2017, 16:02:32) [MSC v.1900 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import os, ctypes
    >>> ctypes.CDLL("msvcrt")._waccess(u"C:\\Windows\\System32\\cmd.exe", os.F_OK)
    0
    >>> ctypes.CDLL("msvcrt")._waccess(u"C:\\Windows\\System32\\cmd.exe.notexist", os.F_OK)
    -1

    Notas :

    • Aunque no es una buena práctica, la estoy usando os.F_OKen la llamada, pero eso es solo por claridad (su valor es 0 )
    • Estoy usando _waccess para que el mismo código funcione en Python3 y Python2 (a pesar de las diferencias relacionadas con Unicode entre ellos)
    • Aunque esto se dirige a un área muy específica, no se mencionó en ninguna de las respuestas anteriores


    La contraparte de Lnx ( Ubtu (16 x64) ) también:

    Python 3.5.2 (default, Nov 17 2016, 17:05:23)
    [GCC 5.4.0 20160609] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import os, ctypes
    >>> ctypes.CDLL("/lib/x86_64-linux-gnu/libc.so.6").access(b"/tmp", os.F_OK)
    0
    >>> ctypes.CDLL("/lib/x86_64-linux-gnu/libc.so.6").access(b"/tmp.notexist", os.F_OK)
    -1

    Notas :

    • En lugar de codificar la ruta de libc ( "/lib/x86_64-linux-gnu/libc.so.6" ) que puede (y muy probablemente variará) entre sistemas, Ninguno (o la cadena vacía) se puede pasar al constructor CDLL ( ctypes.CDLL(None).access(b"/tmp", os.F_OK)) De acuerdo con [man7]: DLOPEN (3) :

      Si el nombre de archivo es NULL, el identificador devuelto es para el programa principal. Cuando se le da a dlsym (), este identificador provoca una búsqueda de un símbolo en el programa principal, seguido de todos los objetos compartidos cargados al inicio del programa, y ​​luego todos los objetos compartidos cargados por dlopen () con el indicador RTLD_GLOBAL .

      • El programa principal (actual) ( python ) está vinculado contra libc , por lo que se cargarán sus símbolos (incluido el acceso )
      • Esto debe manejarse con cuidado, ya que funciones como main , Py_Main y (todas las demás) están disponibles; llamarlos podría tener efectos desastrosos (en el programa actual)
      • Esto tampoco se aplica a Win (pero eso no es un gran problema, ya que msvcrt.dll se encuentra en "% SystemRoot% \ System32" que está en % PATH% por defecto). Quería ir más allá y replicar este comportamiento en Win (y enviar un parche), pero resulta que, [MS.Docs]: la función GetProcAddress solo "ve" los símbolos exportados , por lo que a menos que alguien declare las funciones en el ejecutable principal como __declspec(dllexport)(¿por qué demonios la persona normal haría eso?), el programa principal es cargable pero prácticamente inutilizable
  5. Instalar algún módulo de terceros con capacidades de sistema de archivos

    Lo más probable es que dependa de una de las formas anteriores (tal vez con ligeras personalizaciones).
    Un ejemplo sería (nuevamente, Win específico) [GitHub]: mhammond / pywin32 - Python para Windows (pywin32) Extensiones , que es un contenedor de Python sobre WINAPI .

    Pero, dado que esto es más como una solución, me detengo aquí.

  6. Otra solución (poco convincente ) ( gainarie ) es (como me gusta llamarlo) el enfoque sysadmin : use Python como envoltorio para ejecutar comandos de shell

    • Ganar :

      (py35x64_test) e:\Work\Dev\StackOverflow\q000082831>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" -c "import os; print(os.system('dir /b \"C:\\Windows\\System32\\cmd.exe\" > nul 2>&1'))"
      0
      
      (py35x64_test) e:\Work\Dev\StackOverflow\q000082831>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" -c "import os; print(os.system('dir /b \"C:\\Windows\\System32\\cmd.exe.notexist\" > nul 2>&1'))"
      1
    • Nix ( Lnx ( Ubtu )):

      [cfati@cfati-ubtu16x64-0:~]> python3 -c "import os; print(os.system('ls \"/tmp\" > /dev/null 2>&1'))"
      0
      [cfati@cfati-ubtu16x64-0:~]> python3 -c "import os; print(os.system('ls \"/tmp.notexist\" > /dev/null 2>&1'))"
      512

Línea inferior :

  • Hacer uso try / excepto / persona / por último, bloques, ya que pueden impedir que se ejecuta en una serie de problemas desagradables. Un contraejemplo en el que puedo pensar es el rendimiento: tales bloques son costosos, así que trate de no colocarlos en el código que se supone que debe ejecutarse cientos de miles de veces por segundo (pero dado que (en la mayoría de los casos) implica acceso al disco, No será el caso).

Nota (s) final (es) :

  • Intentaré mantenerlo actualizado, cualquier sugerencia es bienvenida, incorporaré cualquier cosa útil que aparezca en la respuesta

3
¿Puedes dar más detalles sobre esta declaración? "Aunque no es una buena práctica, estoy usando os.F_OK en la llamada, pero eso es solo por claridad (su valor es 0)"
sk8asd123

66
@ sk8asd123: Es difícil hacerlo en un comentario: en general, es mejor usar constantes con funciones con las que se unen. Eso se aplica cuando se trabaja con múltiples módulos que definen la misma constante, porque algunos podrían no estar actualizados, y es mejor que las funciones y las constantes estén sincronizadas. Al trabajar con ctypes (llamando a las funciones directamente), debería haber definido la constante (de MSDN ), o no usar una constante. Es solo una guía que uso, en el 99.9% probablemente no hace ninguna diferencia (funcionalmente).
CristiFati

3
@CristiFati: a partir de 3.6, glob.iglob(y glob.globtambién) se basan enos.scandir , por lo que ahora es vago; para obtener el primer hit en un directorio de archivos de 10M, solo escanea hasta llegar al primer hit. E incluso antes de 3.6, si usa globmétodos sin comodines, la función es inteligente: sabe que solo puede tener un golpe, por lo que simplifica el globbing a solo os.path.isdiroos.path.lexists (dependiendo de si la ruta termina /).
ShadowRanger

3
Esa segunda parte de mi comentario (el globbing sin comodines en realidad no itera la carpeta, y nunca lo ha hecho) significa que es una solución perfectamente eficiente para el problema (más lento que llamar directamente os.path.isdiro os.path.lexistya que es un montón de llamadas a funciones de nivel Python y cadena operaciones antes de que decida que la ruta eficiente es viable, pero no se requiere una llamada adicional al sistema o trabajo de E / S, que es un orden de magnitud más lento).
ShadowRanger

154

Esta es la forma más sencilla de verificar si existe un archivo. El hecho de que el archivo existiera cuando lo verificó no garantiza que estará allí cuando necesite abrirlo.

import os
fname = "foo.txt"
if os.path.isfile(fname):
    print("file does exist at this time")
else:
    print("no such file exists at this time")

17
Mientras tenga la intención de acceder al archivo, la condición de carrera existe , independientemente de cómo se construya su programa. Su programa no puede garantizar que otro proceso en la computadora no haya modificado el archivo. Es a lo que Eric Lippert se refiere como una excepción exógena . No puede evitarlo verificando la existencia del archivo de antemano.
Isaac Supeene

@IsaacSupeene La mejor práctica es hacer que la ventana de operación (de archivo) sea lo más pequeña posible, seguida de un manejo adecuado de excepciones
un33k

145

Python 3.4+ tiene un módulo de ruta orientado a objetos: pathlib . Con este nuevo módulo, puede verificar si existe un archivo como este:

import pathlib
p = pathlib.Path('path/to/file')
if p.is_file():  # or p.is_dir() to see if it is a directory
    # do stuff

Puede (y generalmente debería) seguir usando un try/exceptbloque al abrir archivos:

try:
    with p.open() as f:
        # do awesome stuff
except OSError:
    print('Well darn.')

El módulo pathlib tiene un montón de cosas interesantes en él: engorde conveniente, comprobación del propietario del archivo, unión de ruta más fácil, etc. Vale la pena echarle un vistazo. Si está en una Python anterior (versión 2.6 o posterior), aún puede instalar pathlib con pip:

# installs pathlib2 on older Python versions
# the original third-party module, pathlib, is no longer maintained.
pip install pathlib2

Luego impórtelo de la siguiente manera:

# Older Python versions
import pathlib2 as pathlib

124

Prefiere la declaración de prueba. Se considera mejor estilo y evita las condiciones de carrera.

No confíes en mi palabra. Hay mucho apoyo para esta teoría. Aquí hay una pareja:


3
Agregue mejores fuentes para respaldar su declaración.
BlueTrin

11
El enlace de Evitar condiciones de carrera (soporte de desarrollo de Apple) no respalda su respuesta. Se trata solo del uso de archivos temporales que contienen información confidencial en sistemas operativos mal diseñados que no protegen adecuadamente los archivos / directorios temporales mediante permisos restringidos. Usar try...exceptno ayuda a resolver ese problema de todos modos.
jstine

El problema con este método es que si tiene una pieza importante de código dependiendo del archivo que no existe, ponerlo en la except:cláusula hará que una excepción que surja en esta parte de su código genere un mensaje confuso (se produce un segundo error durante el procesamiento del primero.)
Camion

119

¿Cómo verifico si existe un archivo, usando Python, sin usar una declaración de prueba?

Ahora disponible desde Python 3.4, importe e instancia un Pathobjeto con el nombre del archivo y verifique el is_filemétodo (tenga en cuenta que esto devuelve True para los enlaces simbólicos que apuntan también a archivos normales):

>>> from pathlib import Path
>>> Path('/').is_file()
False
>>> Path('/initrd.img').is_file()
True
>>> Path('/doesnotexist').is_file()
False

Si está en Python 2, puede hacer una copia de seguridad del módulo pathlib desde pypi pathlib2, o verificar isfiledesde el os.pathmódulo:

>>> import os
>>> os.path.isfile('/')
False
>>> os.path.isfile('/initrd.img')
True
>>> os.path.isfile('/doesnotexist')
False

Ahora, lo anterior es probablemente la mejor respuesta directa pragmática aquí, pero existe la posibilidad de una condición de carrera (dependiendo de lo que esté tratando de lograr), y el hecho de que la implementación subyacente usa un try, pero Python usa tryen todas partes en su implementación.

Debido a que Python se usa en trytodas partes, realmente no hay razón para evitar una implementación que lo use.

Pero el resto de esta respuesta intenta considerar estas advertencias.

Respuesta más larga y mucho más pedante

Disponible desde Python 3.4, use el nuevo Pathobjeto en pathlib. Tenga en cuenta que .existsno es del todo correcto, porque los directorios no son archivos (excepto en el sentido de Unix de que todo es un archivo).

>>> from pathlib import Path
>>> root = Path('/')
>>> root.exists()
True

Entonces necesitamos usar is_file:

>>> root.is_file()
False

Aquí está la ayuda sobre is_file:

is_file(self)
    Whether this path is a regular file (also True for symlinks pointing
    to regular files).

Entonces obtengamos un archivo que sabemos que es un archivo:

>>> import tempfile
>>> file = tempfile.NamedTemporaryFile()
>>> filepathobj = Path(file.name)
>>> filepathobj.is_file()
True
>>> filepathobj.exists()
True

De forma predeterminada, NamedTemporaryFileelimina el archivo cuando se cierra (y se cerrará automáticamente cuando no existan más referencias).

>>> del file
>>> filepathobj.exists()
False
>>> filepathobj.is_file()
False

Sin embargo, si profundiza en la implementación , verá que is_fileutiliza try:

def is_file(self):
    """
    Whether this path is a regular file (also True for symlinks pointing
    to regular files).
    """
    try:
        return S_ISREG(self.stat().st_mode)
    except OSError as e:
        if e.errno not in (ENOENT, ENOTDIR):
            raise
        # Path doesn't exist or is a broken symlink
        # (see https://bitbucket.org/pitrou/pathlib/issue/12/)
        return False

Condiciones de carrera: por qué nos gusta probar

Nos gusta tryporque evita las condiciones de carrera. Con try, simplemente intentas leer tu archivo, esperando que esté allí, y si no, capturas la excepción y realizas cualquier comportamiento alternativo que tenga sentido.

Si desea verificar que existe un archivo antes de intentar leerlo, y podría estar borrándolo y luego podría estar usando múltiples hilos o procesos, u otro programa conoce ese archivo y podría borrarlo; corre el riesgo de la posibilidad de una condición de carrera si verifica que existe, porque entonces está corriendo para abrirla antes de que cambie su condición (su existencia).

Las condiciones de carrera son muy difíciles de depurar porque hay una ventana muy pequeña en la que pueden hacer que su programa falle.

Pero si esta es su motivación, puede obtener el valor de una trydeclaración utilizando el suppressadministrador de contexto.

Evitar condiciones de carrera sin una declaración de prueba: suppress

Python 3.4 nos da el suppressadministrador de contexto (anteriormente el ignoreadministrador de contexto), que hace semánticamente exactamente lo mismo en menos líneas, mientras que también (al menos superficialmente) cumple con la solicitud original para evitar una trydeclaración:

from contextlib import suppress
from pathlib import Path

Uso:

>>> with suppress(OSError), Path('doesnotexist').open() as f:
...     for line in f:
...         print(line)
... 
>>>
>>> with suppress(OSError):
...     Path('doesnotexist').unlink()
... 
>>> 

Para Pythons anteriores, puedes tirar el tuyo suppress, pero sin un trywill será más detallado que con. Creo que esta es la única respuesta que no se usa tryen ningún nivel en Python a la que se pueda aplicar antes de Python 3.4 porque en su lugar usa un administrador de contexto:

class suppress(object):
    def __init__(self, *exceptions):
        self.exceptions = exceptions
    def __enter__(self):
        return self
    def __exit__(self, exc_type, exc_value, traceback):
        if exc_type is not None:
            return issubclass(exc_type, self.exceptions)

Quizás más fácil con un intento:

from contextlib import contextmanager

@contextmanager
def suppress(*exceptions):
    try:
        yield
    except exceptions:
        pass

Otras opciones que no cumplen con la solicitud de "sin probar":

isfile

import os
os.path.isfile(path)

de los documentos :

os.path.isfile(path)

Devuelve True si la ruta es un archivo regular existente. Esto sigue los enlaces simbólicos, por lo tanto islink(), y isfile()puede ser cierto para el mismo camino.

Pero si examina el origen de esta función, verá que en realidad usa una instrucción try:

# This follows symbolic links, so both islink() and isdir() can be true
# for the same path on systems that support symlinks
def isfile(path):
    """Test whether a path is a regular file"""
    try:
        st = os.stat(path)
    except os.error:
        return False
    return stat.S_ISREG(st.st_mode)
>>> OSError is os.error
True

Todo lo que está haciendo es usar la ruta dada para ver si puede obtener estadísticas, capturar OSErrory luego verificar si es un archivo si no generó la excepción.

Si tiene la intención de hacer algo con el archivo, le sugiero que intente directamente con una prueba, excepto para evitar una condición de carrera:

try:
    with open(path) as f:
        f.read()
except OSError:
    pass

os.access

Está disponible para Unix y Windows os.access, pero para usar debe pasar banderas, y no diferencia entre archivos y directorios. Esto se usa más para probar si el usuario real que invoca tiene acceso en un entorno de privilegios elevados:

import os
os.access(path, os.F_OK)

También sufre los mismos problemas de condición de carrera que isfile. De los documentos :

Nota: El uso de access () para verificar si un usuario está autorizado para, por ejemplo, abrir un archivo antes de hacerlo usando open () crea un agujero de seguridad, porque el usuario podría explotar el breve intervalo de tiempo entre verificar y abrir el archivo para manipularlo. Es preferible utilizar técnicas EAFP. Por ejemplo:

if os.access("myfile", os.R_OK):
    with open("myfile") as fp:
        return fp.read()
return "some default data"

está mejor escrito como:

try:
    fp = open("myfile")
except IOError as e:
    if e.errno == errno.EACCES:
        return "some default data"
    # Not a permission error.
    raise
else:
    with fp:
        return fp.read()

Evitar el uso os.access. Es una función de bajo nivel que tiene más oportunidades para el error del usuario que los objetos y funciones de nivel superior discutidos anteriormente.

Crítica de otra respuesta:

Otra respuesta dice esto sobre os.access:

Personalmente, prefiero este porque bajo el capó, llama API nativas (a través de "$ {PYTHON_SRC_DIR} /Modules/posixmodule.c"), pero también abre una puerta para posibles errores del usuario, y no es tan Pythonic como otras variantes :

Esta respuesta dice que prefiere un método no pitónico, propenso a errores, sin justificación. Parece alentar a los usuarios a utilizar API de bajo nivel sin comprenderlos.

También crea un administrador de contexto que, al regresar incondicionalmente True, permite que todas las Excepciones (incluidas KeyboardInterrupty SystemExit!) Pasen en silencio, lo cual es una buena manera de ocultar errores.

Esto parece alentar a los usuarios a adoptar malas prácticas.


87
import os
#Your path here e.g. "C:\Program Files\text.txt"
#For access purposes: "C:\\Program Files\\text.txt"
if os.path.exists("C:\..."):   
    print "File found!"
else:
    print "File not found!"

La importación osfacilita la navegación y la realización de acciones estándar con su sistema operativo.

Para referencia también vea ¿Cómo verificar si un archivo existe usando Python?

Si necesita operaciones de alto nivel, use shutil.


99
Esta respuesta es incorrecta. os.path.existsdevuelve verdadero para cosas que no son archivos, como directorios. Esto da falsos positivos. Vea las otras respuestas que recomiendan os.path.isfile.
Chris Johnson

84

Prueba de archivos y carpetas con os.path.isfile(), os.path.isdir()yos.path.exists()

Suponiendo que la "ruta" es una ruta válida, esta tabla muestra lo que devuelve cada función para archivos y carpetas:

ingrese la descripción de la imagen aquí

También puede probar si un archivo es un determinado tipo de archivo os.path.splitext()para obtener la extensión (si aún no lo sabe)

>>> import os
>>> path = "path to a word document"
>>> os.path.isfile(path)
True
>>> os.path.splitext(path)[1] == ".docx" # test if the extension is .docx
True

72

En 2016, la mejor manera sigue usando os.path.isfile:

>>> os.path.isfile('/path/to/some/file.txt')

O en Python 3 puedes usar pathlib:

import pathlib
path = pathlib.Path('/path/to/some/file.txt')
if path.is_file():
    ...

3
Puedo preguntar: ¿Cuál es la ventaja de usar el módulo 'pathlib' en lugar del módulo 'os' en python3 para esta verificación?
Joko

3
pathlibes la solución OOP de python para caminos. Puedes hacer mucho más con eso. Si solo necesita verificar la existencia, la ventaja no es tan grande.
KaiBuxe

65

No parece que haya una diferencia funcional significativa entre try / except y isfile(), por lo que debe usar cuál tiene sentido.

Si desea leer un archivo, si existe, haga

try:
    f = open(filepath)
except IOError:
    print 'Oh dear.'

Pero si solo desea cambiar el nombre de un archivo si existe y, por lo tanto, no necesita abrirlo, haga

if os.path.isfile(filepath):
    os.rename(filepath, filepath + '.old')

Si desea escribir en un archivo, si no existe, haga

# python 2
if not os.path.isfile(filepath):
    f = open(filepath, 'w')

# python 3, x opens for exclusive creation, failing if the file already exists
try:
    f = open(filepath, 'wx')
except IOError:
    print 'file already exists'

Si necesita bloqueo de archivos, ese es un asunto diferente.


3
Esta respuesta es incorrecta. os.path.existsdevuelve verdadero para cosas que no son archivos, como directorios. Esto da falsos positivos. Vea las otras respuestas que recomiendan os.path.isfile.
Chris Johnson

66
En su tercer ejemplo, creo un enlace filepathcon el tiempo correcto, y BAM , sobrescribe el archivo de destino. Debe hacerlo open(filepath, 'wx')en try...exceptbloque para evitar el problema.
espectros

1
En su segundo ejemplo, al menos en Windows, obtendrá un OSErrorif filepath + '.old'ya existe: "En Windows, si dst ya existe, se generará OSError incluso si es un archivo; puede que no haya forma de implementar un cambio de nombre atómico cuando dst nombra un archivo existente ".
Tom Myddeltyn

@TomMyddeltyn: a partir de Python 3.3,os.replace realiza de forma portátil la sustitución silenciosa del archivo de destino (es idéntico al os.renamecomportamiento de Linux de Linux) (solo produce errores si el nombre de destino existe y es un directorio). Así que estás atascado en 2.x, pero los usuarios de Py3 han tenido una buena opción durante varios años.
ShadowRanger

En el renameejemplo: aún debe hacerse con try/ except. os.rename(o os.replaceen Python moderno) es atómico; hacer que se verifique y luego cambiar el nombre introduce una carrera innecesaria y llamadas adicionales al sistema. Just dotry: os.replace(filepath, filepath + '.old') except OSError: pass
ShadowRanger

59

Podrías probar esto (más seguro):

try:
    # http://effbot.org/zone/python-with-statement.htm
    # 'with' is safer to open a file
    with open('whatever.txt') as fh:
        # Do something with 'fh'
except IOError as e:
    print("({})".format(e))

La salida sería:

([Errno 2] No existe tal archivo o directorio: 'whatever.txt')

Luego, dependiendo del resultado, su programa puede seguir ejecutándose desde allí o puede codificar para detenerlo si lo desea.


18
La pregunta original pedía una solución que no utilizatry
rrs

55
Esta respuesta pierde el punto del OP. Comprobar si existe un archivo no es lo mismo que comprobar si puede abrirlo. Habrá casos en los que exista un archivo, pero por varias razones, no puede abrirlo.
Chris Johnson

51

Aunque siempre recomiendo usar tryy exceptdeclaraciones, aquí hay algunas posibilidades para usted (mi favorito personal es usar os.access):

  1. Intenta abrir el archivo:

    Abrir el archivo siempre verificará la existencia del archivo. Puedes hacer una función así:

    def File_Existence(filepath):
        f = open(filepath)
        return True

    Si es False, detendrá la ejecución con un IOError u OSError no administrado en versiones posteriores de Python. Para atrapar la excepción, debe utilizar una cláusula try excepto. Por supuesto, siempre puedes usar una trydeclaración except` como esta (gracias a hsandt por hacerme pensar):

    def File_Existence(filepath):
        try:
            f = open(filepath)
        except IOError, OSError: # Note OSError is for later versions of Python
            return False
    
        return True
  2. Uso os.path.exists(path):

    Esto verificará la existencia de lo que especifique. Sin embargo, busca archivos y directorios, así que ten cuidado con cómo lo usas.

    import os.path
    >>> os.path.exists("this/is/a/directory")
    True
    >>> os.path.exists("this/is/a/file.txt")
    True
    >>> os.path.exists("not/a/directory")
    False
  3. Uso os.access(path, mode):

    Esto verificará si tiene acceso al archivo. Verificará los permisos. Según la documentación de os.py, al escribir os.F_OK, verificará la existencia de la ruta. Sin embargo, usar esto creará un agujero de seguridad, ya que alguien puede atacar su archivo usando el tiempo entre verificar los permisos y abrir el archivo. En su lugar, debe ir directamente a abrir el archivo en lugar de verificar sus permisos. ( EAFP vs LBYP ). Si no va a abrir el archivo después, y solo verifica su existencia, puede usar esto.

    De todos modos, aquí:

    >>> import os
    >>> os.access("/is/a/file.txt", os.F_OK)
    True

También debo mencionar que hay dos formas en que no podrá verificar la existencia de un archivo. O el problema será permission deniedo no such file or directory. Si detecta un IOError, configure el IOError as e(como mi primera opción), y luego escriba print(e.args)para que pueda determinar su problema. ¡Espero que ayude! :)


51

Fecha: 2017-12-04

Todas las soluciones posibles se han enumerado en otras respuestas.

Una forma intuitiva y discutible de verificar si existe un archivo es la siguiente:

import os
os.path.isfile('~/file.md')  # Returns True if exists, else False
# additionaly check a dir
os.path.isdir('~/folder')  # Returns True if the folder exists, else False
# check either a dir or a file
os.path.exists('~/file')

Hice una hoja de trucos exhaustiva para su referencia:

#os.path methods in exhaustive cheatsheet
{'definition': ['dirname',
               'basename',
               'abspath',
               'relpath',
               'commonpath',
               'normpath',
               'realpath'],
'operation': ['split', 'splitdrive', 'splitext',
               'join', 'normcase'],
'compare': ['samefile', 'sameopenfile', 'samestat'],
'condition': ['isdir',
              'isfile',
              'exists',
              'lexists'
              'islink',
              'isabs',
              'ismount',],
 'expand': ['expanduser',
            'expandvars'],
 'stat': ['getatime', 'getctime', 'getmtime',
          'getsize']}

37

Si el archivo es para abrir, puede usar una de las siguientes técnicas:

with open('somefile', 'xt') as f: #Using the x-flag, Python3.3 and above
    f.write('Hello\n')

if not os.path.exists('somefile'): 
    with open('somefile', 'wt') as f:
        f.write("Hello\n")
else:
    print('File already exists!')

ACTUALIZAR

Solo para evitar confusiones y según las respuestas que obtuve, la respuesta actual encuentra un archivo o un directorio con el nombre de pila.


99
Esta respuesta es incorrecta. os.path.existsdevuelve verdadero para cosas que no son archivos, como directorios. Esto da falsos positivos. Vea las otras respuestas que recomiendan os.path.isfile.
Chris Johnson

Tengo el problema falso positivo también.
Zorglub29

docs.python.org/3/library/os.path.html#os.path.exists A la declaración anterior de chris >> os.path.exists (ruta)> Devuelve Verdadero si la ruta se refiere a una ruta existente o abierta descriptor de archivo. Devuelve False para enlaces simbólicos rotos. En algunas plataformas, esta función puede devolver False si no se otorga permiso para ejecutar os.stat () en el archivo solicitado, incluso si la ruta existe físicamente. Cambiado en la versión 3.3: la ruta ahora puede ser un número entero: True se devuelve si es un descriptor de archivo abierto, False de lo contrario. Modificado en la versión 3.6: acepta un objeto similar a una ruta.
JayRizzo

36

Además os.access():

if os.access("myfile", os.R_OK):
    with open("myfile") as fp:
        return fp.read()

Being R_OK, W_OKy X_OKlas banderas para probar los permisos ( doc ).


20
if os.path.isfile(path_to_file):
    try: 
        open(path_to_file)
            pass
    except IOError as e:
        print "Unable to open file"

El aumento de excepciones se considera un enfoque aceptable y Pythonic para el control de flujo en su programa. Considere manejar los archivos que faltan con IOErrors. En esta situación, se generará una excepción IOError si el archivo existe pero el usuario no tiene permisos de lectura.

SRC: http://www.pfinn.net/python-check-if-file-exists.html


3
El OP preguntó cómo verificar si existe un archivo. Es posible que exista un archivo pero que no pueda abrirlo. Por lo tanto, el uso de abrir un archivo como proxy para verificar si el archivo existe no es correcto: tendrá falsos negativos.
Chris Johnson

19

Si ha importado NumPy ya para otros fines, entonces no hay necesidad de importar otras bibliotecas como pathlib, os, paths, etc.

import numpy as np
np.DataSource().exists("path/to/your/file")

Esto devolverá verdadero o falso basado en su existencia.


18

Puedes escribir la sugerencia de Brian sin el try: .

from contextlib import suppress

with suppress(IOError), open('filename'):
    process()

suppresses parte de Python 3.4. En versiones anteriores, puede escribir rápidamente su propia supresión:

from contextlib import contextmanager

@contextmanager
def suppress(*exceptions):
    try:
        yield
    except exceptions:
        pass

17

Soy el autor de un paquete que existe desde hace aproximadamente 10 años, y tiene una función que aborda esta pregunta directamente. Básicamente, si está en un sistema que no es Windows, se utiliza Popenpara acceder find. Sin embargo, si está en Windows, se replicafind con un eficiente caminante de sistema de archivos.

El código en sí no usa un trybloque ... excepto para determinar el sistema operativo y así dirigirlo al estilo "Unix" findo al buillt manual find. Las pruebas de tiempo mostraron que tryera más rápido para determinar el sistema operativo, por lo que utilicé uno allí (pero en ningún otro lugar).

>>> import pox
>>> pox.find('*python*', type='file', root=pox.homedir(), recurse=False)
['/Users/mmckerns/.python']

Y el doctor ...

>>> print pox.find.__doc__
find(patterns[,root,recurse,type]); Get path to a file or directory

    patterns: name or partial name string of items to search for
    root: path string of top-level directory to search
    recurse: if True, recurse down from root directory
    type: item filter; one of {None, file, dir, link, socket, block, char}
    verbose: if True, be a little verbose about the search

    On some OS, recursion can be specified by recursion depth (an integer).
    patterns can be specified with basic pattern matching. Additionally,
    multiple patterns can be specified by splitting patterns with a ';'
    For example:
        >>> find('pox*', root='..')
        ['/Users/foo/pox/pox', '/Users/foo/pox/scripts/pox_launcher.py']

        >>> find('*shutils*;*init*')
        ['/Users/foo/pox/pox/shutils.py', '/Users/foo/pox/pox/__init__.py']

>>>

La implementación, si quiere mirar, está aquí: https://github.com/uqfoundation/pox/blob/89f90fb308f285ca7a62eabe2c38acb87e89dad9/pox/shutils.py#L190


17

Comprobar archivo o directorio existe

Puedes seguir estas tres formas:

Nota 1: Se os.path.isfileusa solo para archivos

import os.path
os.path.isfile(filename) # True if file exists
os.path.isfile(dirname) # False if directory exists

Nota 2: Se os.path.existsutiliza tanto para archivos como para directorios.

import os.path
os.path.exists(filename) # True if file exists
os.path.exists(dirname) #True if directory exists

El pathlib.Pathmétodo (incluido en Python 3+, instalable con pip para Python 2)

from pathlib import Path
Path(filename).exists()

16

Agregar una ligera variación más que no se refleja exactamente en las otras respuestas.

Esto manejará el caso del file_pathser Noneo cadena vacía.

def file_exists(file_path):
    if not file_path:
        return False
    elif not os.path.isfile(file_path):
        return False
    else:
        return True

Agregar una variante basada en la sugerencia de Shahbaz

def file_exists(file_path):
    if not file_path:
        return False
    else:
        return os.path.isfile(file_path)

Agregar una variante basada en la sugerencia de Peter Wood

def file_exists(file_path):
    return file_path and os.path.isfile(file_path):

3
if (x) return true; else return false;es en realidad return x. Tus últimas cuatro líneas pueden convertirse return os.path.isfile(file_path). Mientras estamos en ello, toda la función se puede simplificar como return file_path and os.path.isfile(file_path).
Shahbaz

Hay que tener cuidado con return xen el caso de if (x). Python considerará una cadena vacía Falso, en cuyo caso estaríamos devolviendo una cadena vacía en lugar de un bool. El propósito de esta función es devolver siempre bool.
Marcel Wilson

1
Cierto. En este caso, sin embargo, xes os.path.isfile(..)así que ya es bool.
Shahbaz

os.path.isfile(None)plantea una excepción, por eso agregué el if check. Probablemente podría envolverlo en un intento / excepto en su lugar, pero sentí que era más explícito de esta manera.
Marcel Wilson el

3
return file_path and os.path.isfile(file_path)
Peter Wood

15

Aquí hay un comando Python de 1 línea para el entorno de línea de comandos de Linux. Encuentro esto MUY PRÁCTICO ya que no soy un tipo Bash tan bueno.

python -c "import os.path; print os.path.isfile('/path_to/file.xxx')"

Espero que esto sea útil.


66
Verificación de una línea en bash: [ -f "${file}" ] && echo "file found" || echo "file not found"(que es lo mismo que if [ ... ]; then ...; else ...; fi).
Flotzilla 01 de

12

Puede usar la biblioteca "OS" de Python:

>>> import os
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.txt") 
True
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.tx")
False

55
Esta respuesta es incorrecta. os.path.existsdevuelve verdadero para cosas que no son archivos, como directorios. Esto da falsos positivos. Vea las otras respuestas que recomiendan os.path.isfile.
Chris Johnson

@Chris Johnson, la función os.path.exists () verifica si existe una ruta en el sistema. RUTA puede ser un DIRECTORIO o ARCHIVO. Funcionará bien en ambos casos. Por favor, intente con algún ejemplo
Pradip Das

Entonces, esta respuesta funciona. Excelente. Si la ruta no es la de un archivo. ¿De eso se trataba la pregunta? No.
Debosmit Ray

Depende. Si el objetivo de determinar la existencia de un "archivo" es averiguar si la ruta ya existe (y por lo tanto no es una ruta donde se pueden almacenar nuevos datos sin eliminar otra información), entonces existsestá bien. Si el objetivo es determinar si es seguro abrir un archivo presumiblemente existente, entonces la crítica está justificada y existe no es lo suficientemente precisa. Lamentablemente, el OP no especifica cuál es el objetivo deseado (y probablemente ya no lo hará).
Starturtle

12

¿Cómo verifico si existe un archivo, sin usar la instrucción try?

En 2016, esta podría ser la forma más fácil de verificar si existe un archivo y si es un archivo:

import os
os.path.isfile('./file.txt')    # Returns True if exists, else False

isfileen realidad es solo un método auxiliar que usa internamente os.staty stat.S_ISREG(mode)debajo. Este os.states un método de nivel inferior que le proporcionará información detallada sobre archivos, directorios, sockets, buffers y más. Más acerca de os.stat aquí

Nota: Sin embargo, este enfoque no bloqueará el archivo de ninguna manera y, por lo tanto, su código puede volverse vulnerable al " tiempo de verificación hasta el momento de uso " ( TOCTTOU errores de ).

Por lo tanto, aumentar las excepciones se considera un enfoque aceptable y Pythonic para el control de flujo en su programa. Y uno debería considerar manejar archivos perdidos con IOErrors, en lugar de ifdeclaraciones ( solo un consejo ).


9
import os.path

def isReadableFile(file_path, file_name):
    full_path = file_path + "/" + file_name
    try:
        if not os.path.exists(file_path):
            print "File path is invalid."
            return False
        elif not os.path.isfile(full_path):
            print "File does not exist."
            return False
        elif not os.access(full_path, os.R_OK):
            print "File cannot be read."
            return False
        else:
            print "File can be read."
            return True
    except IOError as ex:
        print "I/O error({0}): {1}".format(ex.errno, ex.strerror)
    except Error as ex:
        print "Error({0}): {1}".format(ex.errno, ex.strerror)
    return False
#------------------------------------------------------

path = "/usr/khaled/documents/puzzles"
fileName = "puzzle_1.txt"

isReadableFile(path, fileName)

@ j6m8 sí, isReadableFile(path,fileName)volverá Truesi el archivo es accesible y legible por el proceso \ program \ thread
Khaled.K
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.