Risposte:
Se il motivo che stai verificando è che puoi fare qualcosa del genere if file_exists: open_it()
, è più sicuro usare un try
around nel tentativo di aprirlo. Il controllo e quindi l'apertura comporta il rischio che il file venga eliminato o spostato o qualcosa tra il momento del controllo e il momento in cui si tenta di aprirlo.
Se non hai intenzione di aprire immediatamente il file, puoi usarlo os.path.isfile
Restituisce
True
se il percorso è un file normale esistente. Questo segue collegamenti simbolici, quindi sia islink () che isfile () possono essere veri per lo stesso percorso.
import os.path
os.path.isfile(fname)
se devi assicurarti che sia un file.
A partire da Python 3.4, il pathlib
modulo offre un approccio orientato agli oggetti (con backport 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, eseguire:
if my_file.is_dir():
# directory exists
Per verificare se Path
esiste un oggetto 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(strict=True)
in un try
blocco:
try:
my_abs_path = my_file.resolve(strict=True)
except FileNotFoundError:
# doesn't exist
else:
# exists
FileNotFoundError
è stato introdotto in Python 3. Se hai bisogno anche di supportare Python 2.7 e Python 3, è possibile utilizzare IOError
invece (che FileNotFoundError
sottoclassi) stackoverflow.com/a/21368457/1960959
open('file', 'r+')
) e poi cercare fino alla fine.
Hai la os.path.exists
funzione:
import os.path
os.path.exists(file_path)
Questo ritorna True
sia per i file che per le directory ma puoi invece usarli
os.path.isfile(file_path)
per verificare se si tratta di un file in particolare. Segue symlink.
A differenza isfile()
, exists()
tornerà True
per le directory. Quindi, a seconda se vuoi solo file semplici o anche directory, utilizzerai isfile()
o exists()
. Ecco alcuni semplici output REPL:
>>> 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
Utilizzare 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")
os.access()
restituirà false.
import os
, non è necessario di import os.path
nuovo in quanto è già parte di os
. Devi solo importare os.path
se intendi utilizzare solo le funzioni da os.path
e non da os
se stesso, per importare una cosa più piccola, ma mentre usi os.access
e os.R_OK
non è necessaria la seconda importazione.
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
Sebbene quasi tutti i modi possibili siano stati elencati in (almeno una delle) risposte esistenti (ad esempio , è stato aggiunto materiale specifico per Python 3.4 ), cercherò di raggruppare tutto insieme.
Nota : ogni pezzo di codice di libreria standard Python che sto per pubblicare, appartiene alla versione 3.5.3 .
Dichiarazione del problema :
Possibili soluzioni :
[Python 3]: os.path. esiste ( percorso ) (controllare anche altri membri della famiglia come funzione os.path.isfile
, os.path.isdir
, os.path.lexists
per leggermente diversi comportamenti)
os.path.exists(path)
Restituisce
True
se percorso fa riferimento a un percorso esistente o a un descrittore di file aperto. RestituisceFalse
per collegamenti simbolici interrotti. Su alcune piattaforme, questa funzione può restituireFalse
se non è stata concessa l'autorizzazione per eseguire os.stat () sul file richiesto, anche se il percorso esiste fisicamente.
Tutto bene, ma se 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 blocco try / tranne intorno a [Python 3]: os. stat ( path, *, dir_fd = None, follow_symlinks = True ) . Quindi, il tuo codice è try / tranne gratuito, ma più in basso nel framestack c'è (almeno) uno di questi blocchi. Questo vale anche per altre funzioni ( incluso os.path.isfile
).
1.1. [Python 3]: Path. is_file ()
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
[Python 3]: 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 os.path.isfile
comportamento (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 3]: contextlib. sopprimere ( * eccezioni ) - che è stato specificamente progettato per sopprimere selettivamente le eccezioni
Ma sembrano essere wrapper per i blocchi try / tranne / else / finally , come [Python 3]: L' istruzione with afferma:
Ciò consente un tentativo comune ... tranne ... infine i modelli di utilizzo da incapsulare per un comodo riutilizzo.
Funzioni di attraversamento del filesystem (e ricerca i risultati per gli articoli corrispondenti)
[Python 3]: os. listdir ( path = '.' ) (o [Python 3]: os. scandir ( path = '.' ) su Python v 3.5 +, backport: [PyPI]: scandir )
Sotto il cofano, entrambi usano:
tramite [GitHub]: python / cpython - (master) cpython / Modules / posixmodule.c
L'uso di scandir () anziché listdir () può aumentare significativamente le prestazioni del codice che necessita anche di informazioni sul tipo di file o sugli attributi di file, poiché gli oggetti os.DirEntry espongono queste informazioni se il sistema operativo le fornisce durante la scansione di una directory. Tutti i metodi os.DirEntry possono eseguire una chiamata di sistema, ma is_dir () e is_file () di solito richiedono solo una chiamata di sistema per collegamenti simbolici; os.DirEntry.stat () richiede sempre una chiamata di sistema su Unix ma ne richiede solo una per i collegamenti simbolici su Windows.
os.listdir
( os.scandir
quando disponibile)glob.glob
)
os.listdir
Dal momento che questi ripetono le cartelle, (nella maggior parte dei casi) sono inefficienti per il nostro problema (ci sono eccezioni, come glob bing non jolly - come sottolineato da @ShadowRanger), quindi non ho intenzione di insistere su di loro. Per non parlare del fatto che in alcuni casi potrebbe essere necessaria l'elaborazione del nome file.
[Python 3]: os. accesso ( percorso, modalità, *, dir_fd = None, effective_ids = false, follow_symlinks = true ) il cui comportamento è vicino a os.path.exists
(in realtà è più ampio, soprattutto a causa della 2 ° argomento)
... verifica se l'utente che ha invocato ha l'accesso specificato al percorso . la modalità dovrebbe essere F_OK per testare l'esistenza del percorso ...
os.access("/tmp", os.F_OK)
Dal momento che anche il lavoro in C , io uso questo metodo anche perché sotto il cofano, chiama nativo API s (di nuovo, tramite "$ {} PYTHON_SRC_DIR /Modules/posixmodule.c" ), ma apre anche una porta per un possibile uso errori , e non è come Python ic come altre varianti. Quindi, come ha giustamente sottolineato @AaronHall, non usarlo a meno che tu non sappia cosa stai facendo:
Nota : è anche possibile chiamare API native tramite [Python 3]: ctypes - Una libreria di funzioni esterne per Python , ma nella maggior parte dei casi è più complicata.
( Specifico per Win ): poiché vcruntime * ( msvcr * ) .dll esporta un [MS.Docs]: _access, _waccess, anche una famiglia di funzioni, 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.notexist", os.F_OK) -1
Note :
os.F_OK
la chiamata, ma è solo per chiarezza (il suo valore è 0 )
Anche la controparte Lnx ( Ubtu (16 x64) ):
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
Note :
Invece il percorso di libc hardcoding ( "/lib/x86_64-linux-gnu/libc.so.6" ) che può (e molto probabilmente, varierà) tra i sistemi, None (o la stringa vuota) può essere passato al costruttore CDLL ( ctypes.CDLL(None).access(b"/tmp", os.F_OK)
). Secondo [man7]: DLOPEN (3) :
Se il nome file è NULL, l'handle restituito è per il programma principale. Se 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 da tutti gli oggetti condivisi caricati da dlopen () con il flag RTLD_GLOBAL .
__declspec(dllexport)
(perché sulla Terra la persona normale dovrebbe farlo?), il programma principale è caricabile ma praticamente inutilizzabileInstalla 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 (di nuovo, specifico di Win ) [GitHub]: mhammond / pywin32 - Estensioni Python per Windows (pywin32) , che è un wrapper Python su WINAPI .
Ma, dato che è più una soluzione alternativa, mi fermo qui.
Un altro (lame) soluzione alternativa ( gainarie ) è (come mi piace chiamarlo) l' approccio sysadmin : usare Python come wrapper per eseguire comandi 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
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
Linea di fondo :
Note finali :
glob.iglob
(e glob.glob
pure) sono basatios.scandir
, quindi ora è pigro; per ottenere il primo hit in una directory di file 10M, scansiona solo fino a raggiungere il primo hit. E anche pre-3.6, se usi glob
metodi senza jolly, la funzione è intelligente: sa che puoi avere solo un colpo, quindi semplifica il globbing a solo os.path.isdir
oos.path.lexists
(a seconda che il percorso finisca /
).
os.path.isdir
o os.path.lexist
poiché è un gruppo di chiamate e stringhe di funzioni a livello di Python operazioni prima che decida che il percorso efficiente è praticabile, ma nessuna chiamata di sistema aggiuntiva o lavoro I / O, che è più lento degli ordini di grandezza).
Questo è il modo più semplice per verificare l'esistenza di un file. Solo perché il file esisteva quando hai controllato non garantisce 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")
Python 3.4+ ha un modulo path orientato agli oggetti: pathlib . Utilizzando questo nuovo modulo, puoi verificare se esiste un file in questo modo:
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 try/except
blocco 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 in esso: comodo globbing, controllo del proprietario del file, accesso più semplice al percorso, ecc. Vale la pena dare un'occhiata. Se utilizzi un Python precedente (versione 2.6 o successiva), puoi comunque 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
Preferisci l'istruzione try. È considerato uno stile migliore ed evita le condizioni di gara.
Non crederci sulla parola. C'è molto supporto per questa teoria. Eccone un paio:
try...except
non aiuta comunque a risolvere questo problema.
except:
clausola si farà in modo che un'eccezione derivante da questa parte del codice genererà un messaggio confuso (secondo errore generato durante l'elaborazione del primo.)
Come posso verificare se esiste un file, usando Python, senza usare un'istruzione try?
Ora disponibile da Python 3.4, importa e crea un'istanza di un Path
oggetto con il nome del file e controlla il is_file
metodo (nota che questo restituisce True anche per i collegamenti simbolici che puntano a file regolari):
>>> from pathlib import Path
>>> Path('/').is_file()
False
>>> Path('/initrd.img').is_file()
True
>>> Path('/doesnotexist').is_file()
False
Se sei su Python 2, puoi eseguire il backport del modulo pathlib da pypi pathlib2
, oppure controllare isfile
dal os.path
modulo:
>>> import os
>>> os.path.isfile('/')
False
>>> os.path.isfile('/initrd.img')
True
>>> os.path.isfile('/doesnotexist')
False
Ora quanto sopra è probabilmente la migliore risposta diretta pragmatica qui, ma c'è la possibilità di una condizione di competizione (a seconda di ciò che stai cercando di realizzare) e il fatto che l'implementazione sottostante usi un try
, ma Python usa try
ovunque nella sua implementazione.
Poiché Python utilizza try
ovunque, non c'è davvero alcun motivo per evitare un'implementazione che lo utilizza.
Ma il resto di questa risposta tenta di considerare questi avvertimenti.
Disponibile da Python 3.4, usa il nuovo Path
oggetto in pathlib
. Nota che .exists
non è del tutto corretto, perché le directory non sono file (tranne nel senso unix che tutto è un file).
>>> from pathlib import Path
>>> root = Path('/')
>>> root.exists()
True
Quindi dobbiamo usare is_file
:
>>> root.is_file()
False
Ecco l'aiuto su is_file
:
is_file(self)
Whether this path is a regular file (also True for symlinks pointing
to regular files).
Quindi otteniamo un file che sappiamo essere un file:
>>> import tempfile
>>> file = tempfile.NamedTemporaryFile()
>>> filepathobj = Path(file.name)
>>> filepathobj.is_file()
True
>>> filepathobj.exists()
True
Per impostazione predefinita, NamedTemporaryFile
elimina il file quando viene chiuso (e si chiuderà automaticamente quando non vi sono più riferimenti).
>>> del file
>>> filepathobj.exists()
False
>>> filepathobj.is_file()
False
Se approfondisci l'implementazione , vedrai che is_file
utilizza 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
Ci piace try
perché evita le condizioni di gara. Con try
, semplicemente provi a leggere il tuo file, aspettandoti che sia lì e, in caso contrario, catturi l'eccezione ed esegui qualunque comportamento di fallback abbia senso.
Se si desidera verificare l'esistenza di un file prima di tentare di leggerlo, è possibile che lo si stia eliminando e quindi si stiano utilizzando più thread o processi oppure un altro programma sia a conoscenza di quel file e possa eliminarlo - si rischia la possibilità di una condizione di gara se la controlli esiste, perché stai quindi correndo per aprirla prima che le sue condizioni (la sua esistenza) cambino.
Le condizioni di gara sono molto difficili da debug perché c'è una finestra molto piccola in cui possono far fallire il tuo programma.
Ma se questa è la tua motivazione, puoi ottenere il valore di una try
dichiarazione usando il suppress
gestore di contesto.
suppress
Python 3.4 ci fornisce il suppress
gestore del contesto (in precedenza il ignore
gestore del contesto), che fa semanticamente esattamente la stessa cosa in meno righe, mentre anche (almeno superficialmente) incontrando l'originale chiede di evitare una try
dichiarazione:
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()
...
>>>
Per i precedenti Pythons, potresti ottenere il tuo suppress
, ma senza un try
sarà più dettagliato che con. Credo che questa sia in realtà l'unica risposta che non viene utilizzata try
a nessun livello in Python a cui può essere applicata prima di Python 3.4 perché utilizza invece un gestore di contesto:
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)
Forse più facile con una prova:
from contextlib import contextmanager
@contextmanager
def suppress(*exceptions):
try:
yield
except exceptions:
pass
isfile
import os
os.path.isfile(path)
dai documenti :
os.path.isfile(path)
Restituisce True se il percorso è un file normale esistente. Questo segue collegamenti simbolici, quindi entrambi
islink()
eisfile()
possono essere veri per lo stesso percorso.
Ma se si esamina l' origine di questa funzione, si vedrà che effettivamente utilizza un'istruzione 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
Tutto ciò che sta facendo è utilizzare il percorso indicato per vedere se è possibile ottenere statistiche su di esso, catturare OSError
e quindi verificare se si tratta di un file se non ha sollevato l'eccezione.
Se hai intenzione di fare qualcosa con il file, ti suggerirei di provarlo direttamente con un tentativo, tranne per evitare una condizione di competizione:
try:
with open(path) as f:
f.read()
except OSError:
pass
os.access
Disponibile per Unix e Windows è os.access
, ma per usare è necessario passare i flag e non fa distinzione tra file e directory. Questo è più usato per verificare se l'utente che ha effettivamente invocato ha accesso in un ambiente con privilegi elevati:
import os
os.access(path, os.F_OK)
Soffre anche degli stessi problemi di razza isfile
. Dai documenti :
Nota: l'uso di access () per verificare se un utente è autorizzato ad es. Ad aprire un file prima di farlo effettivamente utilizzando open () crea una falla di sicurezza, poiché l'utente potrebbe sfruttare l'intervallo di tempo breve tra il controllo e l'apertura del file per manipolarlo. È preferibile utilizzare le tecniche EAFP. Per esempio:
if os.access("myfile", os.R_OK): with open("myfile") as fp: return fp.read() return "some default data"
è meglio scritto come:
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()
Evitare l'uso os.access
. È una funzione di basso livello che ha più opportunità di errore dell'utente rispetto agli oggetti e alle funzioni di livello superiore discussi sopra.
Un'altra risposta dice questo su os.access
:
Personalmente, preferisco questo perché sotto il cofano, chiama API native (tramite "$ {PYTHON_SRC_DIR} /Modules/posixmodule.c"), ma apre anche una porta per possibili errori dell'utente e non è così Pythonic come altre varianti :
Questa risposta afferma che preferisce un metodo non Pythonic, soggetto a errori, senza giustificazione. Sembra incoraggiare gli utenti a utilizzare API di basso livello senza capirle.
Crea anche un gestore di contesto che, ritornando incondizionatamente True
, consente a tutte le Eccezioni (incluso KeyboardInterrupt
e SystemExit
!) Di passare silenziosamente, il che è un buon modo per nascondere i bug.
Ciò sembra incoraggiare gli utenti ad adottare pratiche inadeguate.
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 os
semplifica la navigazione e l'esecuzione di azioni standard con il tuo sistema operativo.
Per riferimento vedi anche Come verificare se esiste un file usando Python?
Se sono necessarie operazioni di alto livello, utilizzare shutil
.
os.path.exists
ritorna vero per cose che non sono file, come le directory. Questo dà falsi positivi. Vedi le altre risposte che raccomandano os.path.isfile
.
Test per file e cartelle con os.path.isfile()
, os.path.isdir()
eos.path.exists()
Supponendo che il "percorso" sia un percorso valido, questa tabella mostra ciò che viene restituito da ciascuna funzione per file e cartelle:
Puoi anche verificare se un file è un determinato tipo di file usando os.path.splitext()
per ottenere l'estensione (se non lo conosci già)
>>> 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
Nel 2016 il modo migliore sta ancora usando os.path.isfile
:
>>> os.path.isfile('/path/to/some/file.txt')
O in Python 3 puoi usare pathlib
:
import pathlib
path = pathlib.Path('/path/to/some/file.txt')
if path.is_file():
...
pathlib
è la soluzione OOP di Python per i percorsi. Puoi fare molto di più con esso. Se hai solo bisogno di controllare l'esistenza, il vantaggio non è così grande.
Non sembra che ci sia una differenza funzionale significativa tra try / tranne 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 solo 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, è una questione diversa.
os.path.exists
ritorna vero per cose che non sono file, come le directory. Questo dà falsi positivi. Vedi le altre risposte che raccomandano os.path.isfile
.
filepath
con il tempismo giusto e , BAM , sovrascrivi il file di destinazione. Dovresti farlo open(filepath, 'wx')
in un try...except
blocco per evitare il problema.
OSError
se filepath + '.old'
esiste già: "Su Windows, se dst esiste già, OSError verrà generato anche se si tratta di un file; potrebbe non esserci modo di implementare una ridenominazione atomica quando dst nomina un file esistente. "
os.replace
esegue in modo portabile la sostituzione silenziosa del file di destinazione (è identico al os.rename
comportamento di Linux) (solo errori se il nome di destinazione esiste ed è una directory). Quindi sei bloccato su 2.x, ma gli utenti di Py3 hanno avuto una buona opzione per diversi anni.
rename
Esempio: Si deve ancora essere fatto con try
/ except
. os.rename
(o os.replace
su Python moderno) è atomico; farlo controllare e poi rinominare introduce una corsa non necessaria e chiamate di sistema aggiuntive. Basta faretry: os.replace(filepath, filepath + '.old') except OSError: pass
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ò continuare a funzionare da lì o puoi programmare per fermarlo se vuoi.
try
Anche se consiglio sempre di usare try
e le except
dichiarazioni, ecco alcune possibilità per te (il mio preferito personale sta usando os.access
):
Prova ad aprire il file:
L'apertura del file verificherà sempre l'esistenza del file. Puoi fare una funzione in questo modo:
def File_Existence(filepath):
f = open(filepath)
return True
Se è False, interromperà l'esecuzione con un IOError o OSError non gestito nelle versioni successive di Python. Per catturare l'eccezione, devi usare una clausola try tranne. Ovviamente, puoi sempre usare try
un'istruzione etc in questo modo (grazie a hsandt
per avermi fatto pensare):
def File_Existence(filepath):
try:
f = open(filepath)
except IOError, OSError: # Note OSError is for later versions of Python
return False
return True
Utilizzare os.path.exists(path)
:
Questo verificherà l'esistenza di ciò che specifichi. Tuttavia, verifica la presenza di file e directory, quindi fai attenzione a come lo usi.
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
Utilizzare os.access(path, mode)
:
Questo verificherà se hai accesso al file. Controllerà le autorizzazioni. Sulla base della documentazione os.py, digitando os.F_OK
, verificherà l'esistenza del percorso. Tuttavia, l'utilizzo di questo creerà un buco nella sicurezza, in quanto qualcuno può attaccare il tuo file usando il tempo tra il controllo delle autorizzazioni e l'apertura del file. Dovresti invece andare direttamente all'apertura del file invece di controllarne le autorizzazioni. ( EAFP vs LBYP ). Se non aprirai il file in un secondo momento e ne controllerai solo l'esistenza, puoi usarlo.
Comunque, qui:
>>> import os
>>> os.access("/is/a/file.txt", os.F_OK)
True
Dovrei anche menzionare che ci sono due modi in cui non sarai in grado di verificare l'esistenza di un file. O il problema sarà permission denied
o no such file or directory
. Se ne prendi uno IOError
, imposta IOError as e
(come la mia prima opzione), quindi digita in print(e.args)
modo da poter sperare di determinare il problema. Spero possa essere d'aiuto! :)
Data: 2017/12/04
Ogni possibile soluzione è stata elencata in altre risposte.
Un modo intuitivo e discutibile per verificare l'esistenza di un file è il seguente:
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')
Ho creato un completo cheatsheet per il tuo riferimento:
#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']}
Se il file è per l'apertura, è possibile utilizzare una delle seguenti tecniche:
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!')
AGGIORNARE
Solo per evitare confusione e in base alle risposte che ho ricevuto, la risposta corrente trova un file o una directory con il nome dato.
os.path.exists
ritorna vero per cose che non sono file, come le directory. Questo dà falsi positivi. Vedi le altre risposte che raccomandano os.path.isfile
.
if os.path.isfile(path_to_file):
try:
open(path_to_file)
pass
except IOError as e:
print "Unable to open file"
Sollevare le eccezioni è considerato un approccio accettabile e Pythonic per il controllo del flusso nel programma. Prendi in considerazione la gestione dei file mancanti con IOErrors. In questa situazione, verrà sollevata un'eccezione IOError se il file esiste ma l'utente non dispone delle autorizzazioni di lettura.
Puoi scrivere il suggerimento di Brian senza il try:
.
from contextlib import suppress
with suppress(IOError), open('filename'):
process()
suppress
fa parte di Python 3.4. Nelle versioni precedenti puoi scrivere rapidamente il tuo soppressore:
from contextlib import contextmanager
@contextmanager
def suppress(*exceptions):
try:
yield
except exceptions:
pass
Sono l'autore di un pacchetto che esiste da circa 10 anni e ha una funzione che risponde direttamente a questa domanda. Fondamentalmente, se ci si trova su un sistema non Windows, utilizza Popen
per accedere find
. Tuttavia, se sei su Windows, si replica find
con un efficiente walker del filesystem.
Il codice stesso non usa un try
blocco ... tranne che per determinare il sistema operativo e quindi indirizzarti allo stile "Unix" find
o al buillt manuale find
. I test di temporizzazione hanno dimostrato che try
era più veloce nel determinare il sistema operativo, quindi ne ho usato uno lì (ma da nessun'altra parte).
>>> import pox
>>> pox.find('*python*', type='file', root=pox.homedir(), recurse=False)
['/Users/mmckerns/.python']
E il 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']
>>>
L'implementazione, se ti interessa guardare, è qui: https://github.com/uqfoundation/pox/blob/89f90fb308f285ca7a62eabe2c38acb87e89dad9/pox/shutils.py#L190
Puoi seguire questi tre modi:
Nota 1:
os.path.isfile
utilizzato solo per i file
import os.path
os.path.isfile(filename) # True if file exists
os.path.isfile(dirname) # False if directory exists
Nota2:
os.path.exists
utilizzato per file e directory
import os.path
os.path.exists(filename) # True if file exists
os.path.exists(dirname) #True if directory exists
Il
pathlib.Path
metodo (incluso in Python 3+, installabile con pip per Python 2)
from pathlib import Path
Path(filename).exists()
Aggiungendo un'altra leggera variazione che non si riflette esattamente nelle altre risposte.
Questo gestirà il caso file_path
dell'essere None
o della stringa vuota.
def file_exists(file_path):
if not file_path:
return False
elif not os.path.isfile(file_path):
return False
else:
return True
Aggiunta di una variante basata sul suggerimento di Shahbaz
def file_exists(file_path):
if not file_path:
return False
else:
return os.path.isfile(file_path)
Aggiunta di una variante basata sul suggerimento di Peter Wood
def file_exists(file_path):
return file_path and os.path.isfile(file_path):
if (x) return true; else return false;
è davvero giusto return x
. Le tue ultime quattro righe possono diventare return os.path.isfile(file_path)
. Mentre ci siamo, l'intera funzione può essere semplificata come return file_path and os.path.isfile(file_path)
.
return x
nel caso di if (x)
. Python considererà una stringa vuota False, nel qual caso restituiremmo una stringa vuota anziché un valore bool. Lo scopo di questa funzione è di restituire sempre il bool.
x
è os.path.isfile(..)
così è già bool.
os.path.isfile(None)
solleva un'eccezione, motivo per cui ho aggiunto il controllo if. Probabilmente potrei semplicemente avvolgerlo in un tentativo / tranne invece, ma ho sentito che era più esplicito in questo modo.
return file_path and os.path.isfile(file_path)
Ecco un comando Python a 1 riga per l'ambiente della riga di comando di Linux. Lo trovo MOLTO COMODO dal momento che non sono un ragazzo Bash così caldo.
python -c "import os.path; print os.path.isfile('/path_to/file.xxx')"
Spero che questo sia utile.
[ -f "${file}" ] && echo "file found" || echo "file not found"
(che è lo stesso di if [ ... ]; then ...; else ...; fi
).
Puoi usare la libreria "OS" di Python:
>>> import os
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.txt")
True
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.tx")
False
os.path.exists
ritorna vero per cose che non sono file, come le directory. Questo dà falsi positivi. Vedi le altre risposte che raccomandano os.path.isfile
.
exists
va bene. Se l'obiettivo è determinare se è sicuro aprire un file presumibilmente esistente, le critiche sono giustificate ed esistono non abbastanza precise. Purtroppo, l'OP non specifica quale sia l'obiettivo desiderato (e probabilmente non lo farà più).
Come posso verificare se esiste un file, senza usare l'istruzione try?
Nel 2016, questo è ancora probabilmente il modo più semplice per verificare se esiste un file e se si tratta di un file:
import os
os.path.isfile('./file.txt') # Returns True if exists, else False
isfile
è in realtà solo un metodo di supporto che utilizza internamente os.stat
e stat.S_ISREG(mode)
sotto. Questo os.stat
è un metodo di livello inferiore che ti fornirà informazioni dettagliate su file, directory, socket, buffer e altro. Maggiori informazioni su os.stat qui
Nota: tuttavia, questo approccio non bloccherà il file in alcun modo e pertanto il codice può diventare vulnerabile ai bug " TOCTTOU " " time of check to time of use " .
Pertanto, sollevare eccezioni è considerato un approccio accettabile e Pythonic per il controllo del flusso nel programma. E si dovrebbe considerare la gestione dei file mancanti con IOErrors, piuttosto che le if
dichiarazioni ( solo un consiglio ).
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)
isReadableFile(path,fileName)
verrà restituito True
se il file è raggiungibile e leggibile dal processo \ programma \ thread