Domanda Come posso verificare se esiste un file?


Come faccio a vedere se un file esiste o no, senza usare il try affermazione?


4346
2017-09-17 12:55


origine


risposte:


Se la ragione per cui stai controllando è così puoi fare qualcosa del genere if file_exists: open_it(), è più sicuro usare a try attorno al tentativo di aprirlo. Il controllo e l'apertura rischiano di eliminare o spostare il file o qualcosa tra il momento in cui si verifica e quando si tenta di aprirlo.

Se non hai intenzione di aprire immediatamente il file, puoi utilizzare os.path.isfile

Ritorno True se path è un file regolare esistente. Questo segue collegamenti simbolici, quindi entrambi islink ()  e isfile ()  può essere vero per lo stesso percorso.

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

se hai bisogno di essere sicuro che sia un file

A partire da Python 3.4, il pathlib modulo  offre un approccio orientato agli oggetti (backported to pathlib2 in Python 2.7):

from pathlib import Path

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

Per controllare una directory, fai:

if my_file.is_dir():
    # directory exists

Per verificare se a Path l'oggetto esiste indipendentemente dal fatto che si tratti di un file o di una directory, utilizzare exists():

if my_file.exists():
    # path exists

Puoi anche usare resolve() in un try bloccare:

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

3947
2017-09-17 12:57



Tu hai il os.path.exists funzione:

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

Questo ritorna True per entrambi i file e le directory, ma puoi invece usare

os.path.isfile(file_name)

per verificare se si tratta di un file specifico. Segue i collegamenti simbolici.


1623
2017-09-17 12:57



a differenza di isfile(), exists() sarà di ritorno True per le directory.
Quindi, a seconda se si desidera solo i file normali o anche le directory, si utilizzerà isfile() o exists(). Ecco un semplice output REPL.

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

834
2017-09-17 15:01



import os.path

if os.path.isfile(filepath):

466
2017-09-17 12:55



Uso 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"

219
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

208
2017-09-17 12:56



Questo è il modo più semplice per verificare se esiste un file. Appena perché  il file esisteva quando non hai controllato garanzia  che sarà lì quando è necessario aprirlo.

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 :

Sebbene quasi tutte le vie possibili siano state elencate in (almeno una delle) risposte esistenti (ad es. Python 3.4  sono state aggiunte cose specifiche), cercherò di raggruppare tutto insieme.

Nota : ogni pezzo di Pitone  codice della libreria standard che sto per postare, appartiene alla versione 3.5.3  (le citazioni dei doc sono versioni 3  specifica).

Dichiarazione problema :

  1. Controlla file ( discutibile : anche cartella ("speciale" file)?) esistenza
  2. Non usare try / except / else / finally blocchi

Possibili soluzioni :

  1. [Python]: os.path. esiste ( sentiero )  (controlla anche altri membri della famiglia di funzioni come os.path.isfile, os.path.isdir, os.path.lexists per comportamenti leggermente diversi)

    os.path.exists(path)
    

    Ritorno True Se sentiero  si riferisce a un percorso esistente oa un descrittore di file aperto. ritorna False per collegamenti simbolici spezzati. Su alcune piattaforme, questa funzione potrebbe tornare False se il permesso non è concesso per l'esecuzione os.stat ()  sul file richiesto, anche se il sentiero  esiste fisicamente

    Tutto bene, ma se si segue l'albero di importazione:

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

      • genericpath.py , linea ~ # 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
        

    è solo un try/exceptbloccare intorno [Python]: os. statistica ( percorso, *, dir_fd = Nessuno, follow_symlinks = True ) . Quindi, il tuo codice è try/except gratis, ma più in basso nel framestack c'è (almeno) uno  tale blocco. Questo vale anche per altre funzioni ( Compreso   os.path.isfile).

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

    • È un fan (e altro ancora pitone ic) modo di gestire i percorsi, ma
    • Sotto il cofano, lo fa Esattamente  la stessa cosa ( pathlib.py , linea ~ # 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 i gestori di contesto delle istruzioni . O:

    • Crearne 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 ...)
      
      • E il suo utilizzo - replicherò il isfile comportamento (notare che questo è solo per scopi dimostrativi, fare non  tenta di scrivere questo codice per produzione ):

        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
        
    • Uso [Python]: contextlib. reprimere ( * eccezioni )  - che era specificamente  progettato per sopprimere selettivamente le eccezioni


    Ma sembrano essere involucri finiti try/except/else/finally blocchi, come [Python]: The con  dichiarazione  stati:

    Questo permette comune provare ... tranne ... finalmente  modelli di utilizzo da incapsulare per un comodo riutilizzo.

  3. Funzioni di attraversamento del filesystem (e cerca i risultati per gli articoli corrispondenti)


    Dal momento che questi iterano su cartelle, (nella maggior parte dei casi) sono inefficienti per il nostro problema (ci sono eccezioni, come non caratteri jolly glob bing - come ha sottolineato @ShadowRanger), quindi non ho intenzione di insistere su di loro. Per non parlare del fatto che in alcuni casi potrebbe essere necessaria l'elaborazione dei nomi dei file.

  4. [Python]: os. accesso ( percorso, modalità, *, dir_fd = Nessuno, effective_ids = False, follow_symlinks = True )  il cui comportamento è vicino a os.path.exists (in realtà è più ampio, principalmente a causa del 2 ND  discussione)

    • permessi dell'utente  potrebbe limitare il file "visibilità" come afferma il documento:

      ... verifica se l'utente che ha richiamato ha l'accesso specificato a sentiero . modalità  dovrebbe essere F_OK  per testare l'esistenza del percorso ...

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

    Dal momento che lavoro anche io C , Uso questo metodo anche perché sotto il cofano, chiama nativo API S  (di nuovo, via "$ {} PYTHON_SRC_DIR /Modules/posixmodule.c" ), ma apre anche un cancello per il possibile errori dell'utente e non è come Pitone ic come altre varianti. Quindi, come ha giustamente sottolineato @AaronHall, non usarlo a meno che tu non sappia cosa stai facendo:

    Nota : chiamata nativa API s è anche possibile via [Pitone]: ctypes  - Una libreria di funzioni straniere per Python , ma nella maggior parte dei casi è più complicato.

    ( Vincere  specifico): Da msvcr * ( vcruntime * ) esporta a [MSDN]: _access, _waccess  funzione famiglia, ecco un esempio:

    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
    

    Gli appunti :

    • Anche se non è una buona pratica, sto usando os.F_OK nella chiamata, ma è solo per chiarezza (il suo valore è 0 )
    • sto usando _waccess in modo che lo stesso codice funzioni python3  e python2  (nonostante unicode  differenze correlate tra loro)
    • Sebbene questo sia rivolto a un'area molto specifica, non è stato menzionato in nessuna delle precedenti risposte


    Il lnx  ( Ubtu (16 x64) ) anche la controparte:

    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
    

    Gli appunti :

    • Invece hardcoding libc il percorso ( "/lib/x86_64-linux-gnu/libc.so.6" ) che possono (e molto probabilmente, saranno) diversi nei sistemi, None (o la stringa vuota) può essere passato a CDLL costruttore ( ctypes.CDLL(None).access(b"/tmp", os.F_OK)). Secondo [uomo]: DLOPEN (3) :

      Se nome del file  è NULL, quindi l'handle restituito è per il principale   programma. Quando dato a dlsym (), questo handle causa una ricerca per a   simbolo nel programma principale, seguito da tutti gli oggetti condivisi caricati in   avvio del programma, quindi tutti gli oggetti condivisi caricati da dlopen () con   la bandiera RTLD_GLOBAL .

      • Programma principale (corrente) ( pitone ) è collegato contro libc , quindi i suoi simboli (incluso access) verrà caricato
      • Questo deve essere gestito con cura, dal momento che funzioni come main, Py_Main e (tutti gli) altri sono disponibili; chiamarli potrebbe avere effetti disastrosi (sul programma attuale)
      • Questo non vale anche per Vincere  (ma non è un grosso problema da allora msvcrt.dll si trova in "% SystemRoot% \ System32"  il quale è in %SENTIERO%  di default). Volevo andare oltre e replicare questo comportamento Vincere  (e invia una patch), ma a quanto pare, [MSDN]: funzione GetProcAddress  solo "vede" esportati  simboli, quindi a meno che qualcuno non dichiari le funzioni nell'eseguibile principale come __declspec(dllexport) (perché sulla Terra il regolare  persona lo farebbe?), il programma principale è caricabile ma praticamente inutilizzabile
  5. Installa alcuni 3 rd  Modulo Party con funzionalità del filesystem

    Molto probabilmente, si baserà su uno dei modi sopra (forse con lievi personalizzazioni).
    Un esempio potrebbe essere (di nuovo, Vincere  specifica) [GitHub]: estensioni Python per Windows (pywin32) , il quale è un Pitone  involucro finito WINAPI S.

    Ma poiché questo è più simile a una soluzione alternativa, mi fermo qui.

  6. Un'altra soluzione (zoppa) ( gainarie ) è (come mi piace chiamarlo) il sysadmin  approccio: usare Pitone  come wrapper per eseguire comandi di shell

    • Vincere :

      (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
      

Linea di fondo :

  • Fare  uso try / except / else / finally blocchi, perché possono impedirti di incorrere in una serie di problemi sgradevoli. Un contro-esempio che posso pensare è la performance: tali blocchi sono costosi, quindi cerca di non metterli in codice che dovrebbe funzionare centinaia di migliaia di volte al secondo (ma dal momento che (nella maggior parte dei casi) comporta l'accesso al disco, non sarà il caso).

Nota (i) finale (s) :

  • Cercherò di tenerlo aggiornato, ogni suggerimento è ben accetto, incorporerò tutto ciò che sarà utile nella risposta

136
2018-06-20 19:28



Python 3.4+  ha un modulo di percorso orientato agli oggetti: pathlib . Usando questo nuovo modulo, puoi verificare se esiste un file come questo:

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

Puoi (e di solito dovresti) usare ancora a try/except blocco all'apertura dei file:

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

Il modulo pathlib ha un sacco di cose interessanti: il globbing conveniente, il controllo del proprietario del file, l'unione più facile dei percorsi, ecc. Vale la pena provarlo. Se sei su un vecchio Python (versione 2.6 o successiva), puoi ancora installare pathlib con pip:

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

Quindi importalo come segue:

# Older Python versions
import pathlib2 as pathlib

121
2018-02-08 02:38