[Python] Come verificare se esiste un file?



Answers

Hai la funzione os.path.exists :

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

Restituisce True per entrambi i file e le directory, ma puoi utilizzare os.path.isfile per verificare se si tratta di un file specifico. Segue i collegamenti simbolici.

Question

Come vedere se un file esiste o no, senza usare la dichiarazione try ?




Additionally, os.access() :

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

Being R_OK , W_OK , and X_OK the flags to test for permissions ( doc ).




import os
path = /path/to/dir

root,dirs,files = os.walk(path).next()
if myfile in files:
   print "yes it exists"

This is helpful when checking for several files. Or you want to do a set intersection/ subtraction with an existing list.




If the file is for opening you could use one of the following techniques:

>>> 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!')



You can use the "OS" library of Python:

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



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 un blocco try/except quando apri i 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 dei percorsi più semplice, 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



2017/12/22 :

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

Nota : ogni parte del codice della libreria standard Python che sto per postare appartiene alla versione 3.5.3 (le virgolette del doc sono specifiche della versione 3 ).

Dichiarazione di problema :

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

Possibili soluzioni :

  1. [Python]: os.path. esiste ( percorso ) (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)
    

    Restituisce True se path fa riferimento a un percorso esistente o a un descrittore di file aperto. Restituisce False per collegamenti simbolici non funzionanti. Su alcune piattaforme, questa funzione può restituire False se non viene concessa l'autorizzazione per eseguire os.stat() sul file richiesto, anche se il percorso esiste fisicamente.

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

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

      • genericpath.py , line ~ # 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/except block around os.stat() os.stat() . Quindi, il tuo codice è try/except free, ma in basso nel framestack c'è (almeno) uno di questi blocchi. Questo vale anche per altre funzioni ( incluso os.path.isfile ).

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

    • È un modo più manieroso (e più python ic) di gestire i percorsi, ma
    • Sotto il cofano, fa esattamente la stessa cosa ( pathlib.py , line ~ # 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 comportamento di isfile (si noti che questo è solo a scopo dimostrativo, non tentare di scrivere tale codice per la 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
        
    • Usa [Python]: contextlib. sopprimere ( * eccezioni ) - che è stato specificamente progettato per sopprimere selettivamente le eccezioni


    Ma, sembrano essere wrapper su try/except/else/finally blocks, come [Python]: The con statement afferma:

    Ciò consente di try comune ... except ... finally 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 queste iterano su cartelle, (nella maggior parte dei casi) sono inefficaci per il nostro problema (ci sono eccezioni, come il bing non glob in caratteri jolly - come sottolineato da @ShadowRanger), quindi non ho intenzione di insistere su di esse. 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 secondo argomento)

    • le autorizzazioni utente potrebbero limitare il file "visibilità" come afferma il documento:

      ... verifica se l'utente che ha richiamato ha l'accesso al percorso specificato. la modalità dovrebbe essere F_OK per verificare l'esistenza del percorso ...

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

    Dato che lavoro anche in C , utilizzo anche questo metodo perché sotto il cofano chiama le API native (di nuovo, tramite " $ {PYTHON_SRC_DIR} /Modules/posixmodule.c "), ma apre anche un gate per un possibile utente errori , e non è come Python come altre varianti. Quindi, come giustamente sottolineato da @AaronHall, non usarlo a meno che tu non sappia cosa stai facendo:

    Nota : la chiamata alle API native è anche possibile tramite [Python]: ctypes - Una libreria di funzioni estranee per Python , ma nella maggior parte dei casi è più complicata.

    ( Win specifico): poiché msvcr * ( vcruntime * ) esporta una famiglia di [MSDN]: _access, _waccess , 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
    

    Note :

    • Anche se non è una buona pratica, sto usando os.F_OK nella chiamata, ma è solo per chiarezza (il suo valore è 0 )
    • Sto usando _waccess modo che lo stesso codice funzioni su Python3 e Python2 (nonostante le differenze relative all'unicode tra di loro)
    • Sebbene si rivolga a un'area molto specifica, non è stata menzionata in nessuna delle precedenti risposte


    La controparte Lnx ( Ubtu (16 x64) ) pure:

    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
    

    Note :

    • Invece di codificare il percorso di libc ( "/lib/x86_64-linux-gnu/libc.so.6" ) che può (e molto probabilmente, sarà) variare tra i sistemi, None (o la stringa vuota) può essere passato al costruttore CDLL ( ctypes.CDLL(None).access(b"/tmp", os.F_OK) ). Secondo [man]: DLOPEN (3) :

      Se il nome del file è NULL, l'handle restituito è per il programma principale. Quando viene assegnato a dlsym (), questo handle provoca la ricerca di un simbolo nel programma principale, seguito da tutti gli oggetti condivisi caricati all'avvio del programma e quindi tutti gli oggetti condivisi caricati da dlopen () con il flag RTLD_GLOBAL .

      • Il programma principale (corrente) ( python ) è collegato alla libc , quindi i suoi simboli (incluso l' access ) verranno caricati
      • Questo deve essere gestito con cura, poiché sono disponibili funzioni come main , Py_Main e (tutti) gli altri; chiamarli potrebbe avere effetti disastrosi (sul programma attuale)
      • Questo non vale anche per Win (ma non è un grosso problema, dal momento che msvcrt.dll si trova in "% SystemRoot% \ System32" che è in % PATH% per impostazione predefinita). Volevo andare oltre e replicare questo comportamento su Win (e inviare una patch), ma come risulta, la funzione [MSDN]: GetProcAddress "vede" solo i simboli esportati , quindi a meno che qualcuno dichiari le funzioni nell'eseguibile principale come __declspec(dllexport) (perché sulla Terra la persona normale lo farebbe?), il programma principale è caricabile ma praticamente inutilizzabile
  5. Installa alcuni moduli di terze parti con funzionalità di filesystem

    Molto probabilmente, si baserà su uno dei modi sopra (forse con lievi personalizzazioni).
    Un esempio potrebbe essere (ancora una volta Win specifico) [GitHub]: Python per Windows (pywin32) Extensions , che è un wrapper Python su WINAPI s.

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

  6. Un'altra soluzione (lame) ( gainarie ) è (come mi piace chiamarla) l'approccio sysadmin : usare Python come wrapper per eseguire i comandi della shell

    • Vincere :

      (py35x64_test) e:\Work\Dev\\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\\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
      

In conclusione :

  • Usa i blocchi try / except / else / finally , perché possono impedirti di incontrare 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 / i :

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



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




I'm the author of a package that's been around for about 10 years, and it has a function that addresses this question directly. Basically, if you are on a non-Windows system, it uses Popen to access find . However, if you are on Windows, it replicates find with an efficient filesystem walker.

The code itself does not use a try block… except in determining the operating system and thus steering you to the "Unix"-style find or the hand-buillt find . Timing tests showed that the try was faster in determining the OS, so I did use one there (but nowhere else).

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

And the doc…

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

>>>

The implementation, if you care to look, is here: https://github.com/uqfoundation/pox/blob/89f90fb308f285ca7a62eabe2c38acb87e89dad9/pox/shutils.py#L190




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

L'importazione di os semplifica la navigazione e l'esecuzione di azioni standard con il tuo sistema operativo.

Per riferimento vedi anche share

Se hai bisogno di operazioni di alto livello, usa shutil .




import os.path

if os.path.isfile(filepath):



Potresti provare questo (più sicuro):

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

L'uscita sarebbe:

([Errno 2] Nessun file o directory di questo tipo: 'whatever.txt')

Quindi, a seconda del risultato, il tuo programma può semplicemente continuare a funzionare da lì o puoi codificarlo per fermarlo se vuoi.




Non sembra che ci sia una differenza funzionale significativa tra try / except e isfile() , quindi dovresti usare quale ha senso.

Se vuoi leggere un file, se esiste, fallo

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

Ma se vuoi semplicemente rinominare un file se esiste, e quindi non è necessario aprirlo, fallo

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

Se vuoi scrivere su un file, se non esiste, fallo

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

Se hai bisogno di bloccare i file, è diverso.




Here's a 1 line Python command for the Linux command line environment. I find this VERY HANDY since I'm not such a hot Bash guy.

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

I hope this is helpful.




import os
os.path.exists(path) # returns whether the path (dir or file) exists or not
os.path.isfile(path) # returns whether the file exists or not



Links