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

6307

¿Cómo verifico si un archivo existe o no, sin usar la trydeclaración?

1
  • 8
    Para verificar si un objeto Path existe independientemente de si es un archivo o directorio, use my_path.exists(). Charlie Parker 6/08/20 a las 19:40
5769

Si la razón por la que está comprobando es para poder hacer algo como if file_exists: open_it(), es más seguro usar un tryalrededor para intentar abrirlo. Verificar y luego abrir corre el riesgo de que el archivo se elimine o mueva o algo entre cuando lo verifica y cuando intenta abrirlo.

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

Return True if path is an existing regular file. This follows symbolic links, so both islink() and isfile() can be true for the same path.

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

si necesita asegurarse de que sea un archivo.

A partir de Python 3.4, el pathlibmódulo ofrece un enfoque orientado a objetos (actualizado pathlib2en Python 2.7):

from pathlib import Path

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

Para consultar un directorio, haga lo siguiente:

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
6
  • 60
    con respecto al primer comentario (use "probar" si se marca antes de abrir) desafortunadamente, esto no funcionará si desea abrir para agregar y asegurarse de que existe antes, ya que el modo 'a' creará si no existe. makapuf 20 de junio de 2018 a las 7:58
  • 12
    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/1960959scottclowe 29/03/19 a las 13:44
  • 13
    @makapuf Puede abrirlo para "actualizar" ( open('file', 'r+')) y luego buscar el final. kyrill 30/04/19 a las 17:45
  • Espera, entonces pathlib2< pathlib? pathlibes para python3, ¿verdad? Lo he estado usando pathlib2pensando que era superior. theX 2 jul.20 a las 21:26
  • 1
    @kyrill: Abrir un archivo para agregarlo no es lo mismo que abrirlo para escribir y buscar el final: cuando tienes escritores concurrentes, se sobrescribirán entre sí sin 'a'. hagello 20/11/20 a las 14:48
2346

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 enlaces simbólicos.

0
1082

A diferencia isfile(), exists()volverá Truepor directorios. Entonces, dependiendo de si solo desea archivos sin formato 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
0
750
import os.path

if os.path.isfile(filepath):
   print("File exists")
0
390

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")
5
  • 66
    tener múltiples condiciones, algunas de las cuales son superfluas, es menos claro y explícito. wim 9 de abril de 2013 a las 5:45
  • 14
    También es redundante. Si el archivo no existe, os.access()devolverá falso. user207421 13/03/18 a las 0:01
  • 9
    @EJP En Linux, los archivos pueden existir pero no son accesibles. e-info128 16 jul 2018 a las 21:30
  • 9
    ya que usted import os, no es necesario que import os.pathvuelva a hacerlo, ya que ya es parte de os. Solo necesita importar os.pathsi solo va a usar funciones desde os.pathy no desde ossí mismo, para importar una cosa más pequeña, pero a medida que usa os.accessy os.R_OK, la segunda importación no es necesaria. Jester 24/08/18 a las 13:10
  • 1
    Comprobar si el usuario tiene derechos de acceso para leer el archivo es muy profesional. A menudo, los datos están en la unidad local durante el desarrollo y en la red compartida en prod. Entonces esto podría llevar a tal situación. Además, el código es perfectamente claro, legible y explícito. Martin Meeser 2 jul.20 a las 7:04
326
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
1
  • 6
    Por lo general, no es una buena práctica nombrar las variables de la misma manera que los nombres de los métodos. Homunculus Reticulli 3 abr.20 a las 17:10
265

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. Verificar archivo ( discutible : ¿también carpeta (archivo "especial")?) Existencia
  2. No utilice try / excepto / else / finalmente bloques

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)
    

    Return True if path refers to an existing path or an open file descriptor. Returns False for broken symbolic links. On some platforms, this function may return False if permission is not granted to execute os.stat() on the requested file, even if the path physically exists.

    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 = True ) . Entonces, su código es try / except free, pero más abajo en el framestack hay (al menos) uno de esos bloques. Esto también se aplica a otras funciones ( incluidas os.path.isfile ).

    1.1. [Python 3]: ruta. es_archivo ()

    • Es una forma más elegante (y más python ic) de manejar las rutas, pero
    • Bajo el 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 administradores de contexto de declaraciones . Cualquiera:

    • 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 excepciones de forma selectiva


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

    This allows common try...except...finally usage patterns to be encapsulated for convenient reuse.

  3. Funciones de recorrido del sistema de archivos (y búsqueda de resultados para elementos coincidentes)


    Dado que estos iteran sobre carpetas, (en la mayoría de los casos) son ineficientes para nuestro problema (hay excepciones, como glob bing sin comodines , como señaló @ShadowRanger), por lo que no voy a insistir en ellos. Sin mencionar que, en algunos casos, es posible que sea necesario procesar el nombre de archivo.

  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:

      ...test if the invoking user has the specified access to path. mode should be F_OK to test the existence of path...

    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 @AaronHall señaló correctamente, no lo use a menos que sepa lo que está haciendo:

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

    ( Específico de Win ): dado que vcruntime * ( msvcr * ) .dll también exporta una familia de funciones [MS.Docs]: _access, _waccess , 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, lo estoy usando os.F_OKen la llamada, pero eso es solo para mayor 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, None (o la cadena vacía) se puede pasar al constructor CDLL ( ctypes.CDLL(None).access(b"/tmp", os.F_OK)). Según [man7]: DLOPEN (3) :

      If filename is NULL, then the returned handle is for the main program. When given to dlsym(), this handle causes a search for a symbol in the main program, followed by all shared objects loaded at program startup, and then all shared objects loaded by dlopen() with the flag RTLD_GLOBAL.

      • El programa principal (actual) ( python ) está vinculado a 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) otras 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% de forma predeterminada). Quería ir más allá y replicar este comportamiento en Win (y enviar un parche), pero resulta que la función [MS.Docs]: GetProcAddress solo "ve" los símbolos exportados , así que a menos que alguien declare las funciones en el ejecutable principal ya que __declspec(dllexport)(¿por qué diablos la persona normal haría eso?), el programa principal es cargable pero prácticamente inutilizable
  5. Instale 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, específico de Win ) [GitHub]: mhammond / pywin32 - Extensiones de Python para Windows (pywin32) , que es una envoltura de Python sobre WINAPI .

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

  6. Otra (pobre) solución ( gainarie ) es (como me gusta llamarlo) el enfoque de administrador de sistemas : 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 )):

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

Conclusión :

  • 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 un 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 surja en la respuesta.
4
  • 3
    ¿Puede ampliar esta afirmació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 19 de noviembre de 2017 a las 1:46
  • 6
    @ sk8asd123: Es un poco difícil hacerlo en un comentario: en general, es mejor usar constantes con funciones con las que se combinan. Eso se aplica cuando se trabaja con varios módulos que definen la misma constante, porque es posible que algunos no estén 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 en absoluto. Es solo una pauta que utilizo, en el 99,9% probablemente no hace ninguna diferencia (funcionalmente). CristiFati 19/11/2017 a las 23:54
  • 3
    @CristiFati: A partir de 3.6, glob.iglob(y glob.globtambién) se basan enos.scandir , por lo que ahora es perezoso; para obtener el primer resultado en un directorio de 10 millones de archivos, solo escanee hasta llegar al primer resultado. E incluso antes de 3.6, si usa globmétodos sin comodines, la función es inteligente: sabe que solo puede tener un hit, por lo que simplifica el globbing a solo os.path.isdiroos.path.lexists (dependiendo de si la ruta termina en /). ShadowRanger 29/11/2017 a las 18:29
  • 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 al problema (más lento que llamar directamente os.path.isdiro os.path.lexistya que es un montón de llamadas de función de nivel de Python y cadena operaciones antes de que decida que la ruta eficiente es viable, pero ninguna llamada al sistema adicional o trabajo de E / S, que es un orden de magnitud más lento). ShadowRanger 29/11/2017 a las 18:38
197

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 debe) usar 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: globbing conveniente, comprobación del propietario del archivo, unión de rutas más fácil, etc. Vale la pena echarle un vistazo. Si está en un 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
1
159

Esta es la forma más sencilla de comprobar si existe un archivo. El hecho de que el archivo existiera cuando lo marcó 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")
2
  • 17
    Siempre que tenga la intención de acceder al archivo, la condición de carrera existe , independientemente de cómo esté construido 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 comprobando la existencia del archivo de antemano. Isaac Supeene 23/11/2014 a las 18:37
  • @IsaacSupeene La mejor práctica es hacer que la ventana de operación (archivo) sea lo más pequeña posible seguida de un manejo adecuado de excepcionesun33k 28/07/18 a las 2:52
131

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

No confíe en mi palabra. Hay mucho apoyo para esta teoría. Aquí hay un par:

3
  • 3
    Agregue mejores fuentes para respaldar su declaración. BlueTrin 10 de septiembre de 2015 a las 9:09
  • 11
    El enlace citado 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 a través de permisos restringidos. El uso try...exceptno ayuda a resolver ese problema de todos modos. jstine 28 de septiembre de 2015 a las 15:38
  • El problema con este método es que si tiene un fragmento 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 generará un mensaje confuso (segundo error generado durante el procesamiento del primero.)Camion 24 de mayo de 2019 a las 10:43
130

How do I check whether a file exists, using Python, without using a try statement?

Ahora disponible desde Python 3.4, importe y cree una instancia de un Pathobjeto con el nombre de archivo y verifique el is_filemétodo (tenga en cuenta que esto devuelve True para los enlaces simbólicos que apuntan 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 realizar una copia de respaldo del módulo pathlib desde pypi pathlib2, o de lo contrario 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 a try, pero Python usa tryen todas partes en su implementación.

Debido a que Python lo 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, 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).

Así que 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 a él).

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

Sin embargo, si profundiza en la implementación , verá que is_fileusa 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 intenta leer su archivo, esperando que esté allí, y si no, detecta la excepción y realiza cualquier comportamiento de respaldo que tenga sentido.

Si desea comprobar que existe un archivo antes de intentar leerlo, y es posible que lo esté eliminando y luego esté utilizando varios subprocesos o procesos, u otro programa conozca ese archivo y podría eliminarlo, corre el riesgo de una condición de carrera si comprueba 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 semánticamente hace 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()
... 
>>> 

En el caso de Pythons anteriores, podrías rodar el tuyo propio suppress, pero sin un tryserá más detallado que con. Creo que esta es en realidad la única respuesta que no se usa tryen ningún nivel en Python que se puede aplicar antes de Python 3.4 porque usa un administrador de contexto en su lugar:

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 "sin intentarlo":

isfile

import os
os.path.isfile(path)

de los documentos :

os.path.isfile(path)

Return True if path is an existing regular file. This follows symbolic links, so both islink() and isfile() can be true for the same path.

Pero si examina la fuente de esta función, verá que en realidad usa una declaració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, detectar 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 lo intente directamente con un intento, 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 usarlo debe pasar banderas, y no diferencia entre archivos y directorios. Esto se usa más para probar si el usuario 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 :

Note: Using access() to check if a user is authorized to e.g. open a file before actually doing so using open() creates a security hole, because the user might exploit the short time interval between checking and opening the file to manipulate it. It’s preferable to use EAFP techniques. For example:

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

is better written as:

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()

Evite el uso os.access. Es una función de bajo nivel que tiene más oportunidades de 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:

Personally, I prefer this one because under the hood, it calls native APIs (via "${PYTHON_SRC_DIR}/Modules/posixmodule.c"), but it also opens a gate for possible user errors, and it's not as Pythonic as other variants:

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

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

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

0
90

Las pruebas para detectar 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 cierto tipo de archivo usando os.path.splitext()para obtener la extensión (si aún no la conoce)

>>> 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
0
90
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.

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

Si necesita operaciones de alto nivel, use shutil.

1
  • 10
    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 1 de agosto de 2015 a las 13:56
76

En 2016, la mejor forma sigue utilizando 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():
    ...
2
  • 4
    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 25 de febrero de 2016 a las 8:55
  • 4
    pathlibes la solución OOP de Python para rutas. Puedes hacer mucho más con él. Si solo necesita verificar la existencia, la ventaja no es tan grande. KaiBuxe 25/0216 a las 10:44
69

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, eso es un asunto diferente.

5
  • 4
    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 1 de agosto de 2015 a las 13:54
  • 6
    En su tercer ejemplo, creo un enlace filepathcon el nombre en el momento adecuado, y BAM , sobrescribe el archivo de destino. Debe hacerlo open(filepath, 'wx')en try...exceptbloque para evitar el problema. spectras 24/08/15 a las 14:05
  • 1
    En su segundo ejemplo, al menos en Windows, obtendrá un OSErrorif filepath + '.old'ya existe: "En Windows, si dst ya existe, OSError se generará incluso si es un archivo; es posible que no haya forma de implementar un cambio de nombre atómico cuando dst nombra un archivo existente ". Tom Myddeltyn 24 de mayo de 2016 a las 14:14
  • @TomMyddeltyn: A partir de Python 3.3,os.replace realiza de forma portátil el reemplazo silencioso del archivo de destino (es idéntico al os.renamecomportamiento de Linux) (solo genera errores si el nombre de destino existe y es un directorio). Así que está atascado en 2.x, pero los usuarios de Py3 han tenido una buena opción durante varios años. ShadowRanger 29/11/2017 a las 18:14
  • En el renameejemplo: todavía debería hacerse con try/ except. os.rename(o os.replaceen Python moderno) es atómico; hacer que se compruebe y luego se cambie el nombre introduce una carrera innecesaria y llamadas al sistema adicionales. Solo hazlotry: os.replace(filepath, filepath + '.old') except OSError: pass ... ShadowRanger 29/11/2017 a las 18:17
62

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 such file or directory: 'whatever.txt')

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

2
  • 20
    La pregunta original pedía una solución que no utilizatryrrs 23/04/2014 a las 13:10
  • 6
    Esta respuesta pierde el sentido 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 diversas razones, no podrá abrirlo. Chris Johnson 17/02/2016 a las 18:52
54

Fecha: 2017-12-04

Todas las posibles soluciones se han enumerado en otras respuestas.

Una forma intuitiva y discutible de comprobar 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 referencia 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']}
0
53

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

  1. Intente 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 o OSError sin mano en versiones posteriores de Python. Para detectar la excepción, debe usar una cláusula try except. 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. Utilizar os.path.exists(path):

    Esto comprobará la existencia de lo que especifique. Sin embargo, busca archivos y directorios, así que tenga cuidado con cómo lo usa.

    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. Utilizar os.access(path, mode):

    Esto comprobará si tiene acceso al archivo. Verificará los permisos. Basado en la documentación de os.py, escribiendo 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 la verificación de los permisos y la apertura del archivo. En su lugar, debe ir directamente a abrir el archivo en lugar de verificar sus permisos. ( EAFP frente a 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 las 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, con suerte, pueda determinar su problema. ¡Espero que ayude! :)

40

Además, os.access():

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

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

40

Si el archivo es para abrir, puede utilizar 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.

3
  • 9
    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 1 de agosto de 2015 a las 13:55
  • También obtuve el problema de los falsos positivos. Zorglub29 19 de mayo de 2018 a las 21:33
  • docs.python.org/3/library/os.path.html#os.path.exists A la declaración anterior de chris >> os.path.exists (ruta)> Devuelve True 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. Modificado en la versión 3.3: la ruta ahora puede ser un número entero: se devuelve verdadero si es un descriptor de archivo abierto, falso en caso contrario. Modificado en la versión 3.6: Acepta un objeto similar a una ruta. JayRizzo 31/08/18 a las 23:24
36

La forma más sencilla de hacerlo es con

import os

if os.path.exists(FILE):
  # file exists
  pass
else:
  # file does not exists
  pass

de la biblioteca del sistema operativo, mientras que FILE es la ruta relativa. En Windows, esto puede o no funcionar y es posible que tenga que usar la ruta de absolución al hacerlo os.path.exists(os.path.join(os.path.abspath('./'), FILE)), donde FILE sigue siendo la ruta relativa más el nombre del archivo

33

TL; DR usa el módulo pathlib con una sola línea de código.

Pathlib es probablemente la forma más moderna y conveniente para casi todas las operaciones de archivos. Para la existencia de un archivo o una carpeta basta con una sola línea de código.

from pathlib import Path

if Path("myfile.txt").exists(): # works for both file and folders
    # do your cool stuff...

El pathlibmódulo se introdujo en Python 3.4, por lo que necesita tener Python 3.4+, esta biblioteca le hace la vida mucho más fácil mientras trabaja con archivos y carpetas y es bastante útil, aquí hay más documentación al respecto ( https: //docs.python. org / 3 / library / pathlib.html ).

Por cierto, si va a reutilizar la ruta, entonces es mejor asignarla a una variable

así se convertirá

from pathlib import Path

p = Path("loc/of/myfile.txt")
if p.exists(): # works for both file and folders
    # do stuffs...
#reuse 'p' if needed.
1
  • Tenga en cuenta que esto devuelve True si el archivo no está presente pero existe la ruta al archivo. Si está realmente interesado en preguntar si el archivo existe o no, debería usar p.is_file ()bravhek 25 de junio a las 21:38
24

Puede utilizar os.path.exists ():

import os
print(os.path.exists("file"))

Espero que ayude: D

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

Raising exceptions is considered to be an acceptable, and Pythonic, approach for flow control in your program. Consider handling missing files with IOErrors. In this situation, an IOError exception will be raised if the file exists but the user does not have read permissions.

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

1
  • 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, usar la apertura de un archivo como proxy para verificar si el archivo existe no es correcto: tendrá falsos negativos. Chris Johnson 17/02/2016 a las 18:58
21

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 según su existencia.

19

Puede 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
18

Verifique que el archivo o directorio exista

Puedes seguir estas tres formas:

Note1: The os.path.isfile used only for files

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

Note2: The os.path.exists used for both files and directories

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

The pathlib.Path method (included in Python 3+, installable with pip for Python 2)

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

Agregando una pequeña 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)

Añadiendo una variante basada en la sugerencia de Peter Wood

def file_exists(file_path):
    return file_path and os.path.isfile(file_path):
5
  • 3
    if (x) return true; else return false;es realmente justo return x. Tus últimas cuatro líneas pueden convertirse en return os.path.isfile(file_path). Ya que estamos en eso, toda la función se puede simplificar como return file_path and os.path.isfile(file_path). Shahbaz 4 de ene. De 2017 a las 22:50
  • Tienes que tener cuidado con return xen el caso de if (x). Python considerará una cadena vacía como False, en cuyo caso estaríamos devolviendo una cadena vacía en lugar de un bool. El propósito de esta función es siempre devolver bool. Marcel Wilson 5 de ene. De 2017 a las 17:08
  • 1
    Verdadero. En este caso, sin embargo, xes os.path.isfile(..)por lo que ya ha bool. Shahbaz 5 de ene. De 2017 a las 17:10
  • os.path.isfile(None)genera una excepción, por lo que agregué la verificación if. Probablemente podría simplemente envolverlo en un intento / excepto en su lugar, pero sentí que era más explícito de esta manera. Marcel Wilson 5 de ene. De 2017 a las 17:13
  • 3
    return file_path and os.path.isfile(file_path)Peter Wood 6/04/2017 a las 10:35
17

Soy el autor de un paquete que existe desde hace unos 10 años y tiene una función que aborda esta cuestión directamente. Básicamente, si está en un sistema que no es Windows, usa Popenpara acceder find. Sin embargo, si está en Windows, se replica findcon un eficiente sistema de archivos.

El código en sí no usa un trybloque ... excepto para determinar el sistema operativo y, por lo tanto find, llevarlo al estilo "Unix" o al manual find. Las pruebas de tiempo mostraron que tryfue más rápido para determinar el sistema operativo, así que usé 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 le interesa mirar, está aquí: https://github.com/uqfoundation/pox/blob/89f90fb308f285ca7a62eabe2c38acb87e89dad9/pox/shutils.py#L190

16

Aquí hay un comando de 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 caliente.

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

Espero que esto sea útil.

1
  • 6
    Comprobació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 1/10/15 a las 7:48