Pregunta ¿Cómo puedo verificar si existe un archivo?


¿Cómo veo si un archivo existe o no, sin usar el try ¿declaración?


4347
2017-09-17 12:55


origen


Respuestas:


Si la razón por la que está comprobando es para que pueda hacer algo como if file_exists: open_it(), es más seguro usar un try alrededor del intento de abrirlo. Verificar y luego abrir corre el riesgo de que se elimine o mueva el archivo o algo entre el momento en que lo comprueba y el momento en que intenta abrirlo.

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

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

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

si necesita estar seguro de que es un archivo.

Comenzando con Python 3.4, el pathlib módulo ofrece un enfoque orientado a objetos (backported a pathlib2 en Python 2.7):

from pathlib import Path

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

Para verificar un directorio, hazlo:

if my_file.is_dir():
    # directory exists

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

if my_file.exists():
    # path exists

También puedes usar resolve() en un try bloquear:

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

3949
2017-09-17 12:57



Tienes el os.path.exists función:

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

Esto regresa True para ambos archivos y directorios, pero en su lugar puede usar

os.path.isfile(file_name)

para probar si se trata de un archivo específicamente. Sigue los enlaces simbólicos.


1624
2017-09-17 12:57



diferente a isfile(), exists() regresará True para directorios.
Entonces, dependiendo de si solo quiere archivos simples o también directorios, usará isfile() o exists(). Aquí hay una salida REPL simple.

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

835
2017-09-17 15:01



import os.path

if os.path.isfile(filepath):

467
2017-09-17 12:55



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

import os
import os.path

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"

220
2018-01-16 05:57



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

209
2017-09-17 12:56



Esta es la forma más sencilla de verificar si existe un archivo. Sólo porque el archivo existía cuando marcó no lo hace garantía que estará allí cuando necesites 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")

138
2018-06-27 13:38



2017/12/22:

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

Nota: cada pieza de Pitón el código de biblioteca estándar que voy a publicar, pertenece a la versión 3.5.3 (Las citas de doc son versión 3 específico).

Planteamiento del problema:

  1. Verificar archivo (discutible: también carpeta (archivo "especial")?) existencia
  2. No usar try / except / else / finally bloques

Soluciones posibles:

  1. [Python]: os.path.existe(camino) (también verifique otros miembros de la familia de la función como os.path.isfile, os.path.isdir, os.path.lexists para comportamientos levemente diferentes)

    os.path.exists(path)
    

    Regreso True Si camino se refiere a una ruta existente o un descriptor de archivo abierto. Devoluciones False para enlaces simbólicos rotos. En algunas plataformas, esta función puede regresar False si el permiso no se concede para ejecutar os.stat () en el archivo solicitado, incluso si el camino físicamente existe.

    Todo bien, pero si sigues 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 solamente un try/except bloquear alrededor [Python]: os.stat(ruta, *, dir_fd = Ninguna, follow_symlinks = True). Entonces, tu código es try/except gratis, pero más bajo en el marco hay (al menos) uno tal bloque. Esto también se aplica a otros funcs (incluso  os.path.isfile)

    1.1. [Python]: pathlib.Path.is_file()

    • Es más elegante (y más pitónic) Manera de manejar caminos, pero
    • Bajo el capó, lo hace exactamente la misma cosa (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]: 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 - Voy a replicar el isfile comportamiento (tenga en cuenta que esto es solo para demostrar propósitos, hacer no intentar escribir dicho código para 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
        
    • Utilizar [Python]: contextlib.reprimir(* excepciones) - que era específicamente diseñado para suprimir selectivamente excepciones


    Pero, parecen ser envoltorios sobre try/except/else/finally bloques, como [Python]: el con declaración estados:

    Esto permite común tratar...excepto...finalmente patrones de uso a encapsular para una reutilización conveniente.

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


    Dado que estos iteran sobre carpetas, (en la mayoría de los casos) son ineficaces para nuestro problema (hay excepciones, como no comodín globbing - como señaló @ShadowRanger), así que no voy a insistir en ellos. Sin mencionar que, en algunos casos, es posible que se requiera el procesamiento del nombre de archivo.

  4. [Python]: os.acceso(ruta, modo, *, dir_fd = Ninguno, effective_ids = False, follow_symlinks = True) cuyo comportamiento es cercano a os.path.exists (en realidad es más amplio, principalmente debido a los 2Dakota del Norte argumento)

    • Permisos de usuario podría restringir el archivo "visibilidad" como dice el documento:

      ... probar si el usuario que realiza la invocación tiene el acceso especificado a camino. modo debiera ser F_OK para probar la existencia del camino ...

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

    Como también trabajo en do, Uso este método también porque bajo el capó, llama nativo APIs (de nuevo, a través de "$ {PYTHON_SRC_DIR} /Modules/posixmodule.c"), pero también abre una puerta para posibles errores de usuarioy no es tan Pitónic como otras variantes. Entonces, como @AaronHall correctamente señaló, no lo use a menos que sepa lo que está haciendo:

    Nota: llamando nativo APIs también es posible a través de [Pitón]: ctypes - Una biblioteca de funciones extranjeras para Python, pero en la mayoría de los casos es más complicado.

    (Ganar específico): desde msvcr *(vcruntime *) exporta una [MSDN]: _access, _waccess familia de funciones también, he aquí 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", os.F_OK)
    -1
    

    Notas:

    • 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)
    • Estoy usando _waccess para que el mismo código funcione en Python3 y Python2 (a pesar de Unicode diferencias relacionadas entre ellos)
    • Aunque esto apunta a un área muy específica, no fue mencionado en ninguna de las respuestas anteriores


    los Lnx (Ubtu (16 x64)) contraparte 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"/tmp1", os.F_OK)
    -1
    

    Notas:

    • En lugar de hardcoding libcel camino de"/lib/x86_64-linux-gnu/libc.so.6") que puede (y muy probablemente variará) a través de los sistemas, None (o la cadena vacía) se puede pasar a CDLL constructor (ctypes.CDLL(None).access(b"/tmp", os.F_OK)) De acuerdo a [hombre]: DLOPEN (3):

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

      • Programa principal (actual) (pitón) está vinculado contra libc, entonces sus símbolos (incluyendo access) será cargado
      • Esto debe manejarse con cuidado, ya que funciones como main, Py_Main y (todos) otros están disponibles; llamarlos podría tener efectos desastrosos (en el programa actual)
      • Esto tampoco se aplica a Ganar (pero eso no es un gran problema, ya que msvcrt.dllSe encuentra en "% SystemRoot% \ System32" Qué esta en %CAMINO% por defecto). Quería llevar las cosas más lejos y replicar este comportamiento en Ganar (y envíe un parche), pero resulta que [MSDN]: función GetProcAddress solo "ve" exportado símbolos, a menos que alguien declare las funciones en el ejecutable principal como __declspec(dllexport) (¿Por qué en la Tierra regular persona haría eso?), el programa principal es cargable pero casi inutilizable
  5. Instala algunos 3rd Módulo de fiesta con capacidades de sistema de archivos

    Lo más probable es que confíe en una de las formas anteriores (tal vez con pequeñas personalizaciones).
    Un ejemplo sería (nuevamente, Ganar específico) [GitHub]: extensiones de Python para Windows (pywin32), el cual es un Pitón envoltura sobre WINAPIs.

    Pero, como esto es más como una solución alternativa, me estoy deteniendo aquí.

  6. Otra solución (coja) (gainarie) es (como me gusta llamarlo) el sysadmin enfoque: uso Pitón como un contenedor 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
      
    • 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 de fondo:

  • Hacer utilizar try / except / else / finally bloques, porque pueden evitar que se encuentre con una serie de problemas desagradables. Un contraejemplo 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):

  • Trataré de mantenerlo actualizado, cualquier sugerencia es bienvenida, incorporaré todo lo útil que surja en la respuesta

136
2018-06-20 19:28



Python 3.4+ tiene un módulo de ruta orientada a objetos: pathlib. Usando este nuevo módulo, puede verificar si un archivo existe así:

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

Puedes (y siempre deberías) seguir usando un try/except bloquear al abrir archivos:

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

El módulo pathlib tiene muchas cosas interesantes: comodín 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 una versión anterior de Python (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órtalo de la siguiente manera:

# Older Python versions
import pathlib2 as pathlib

121
2018-02-08 02:38