Antworten:
Wenn der Grund, den Sie überprüfen, darin besteht, dass Sie so etwas tun können if file_exists: open_it()
, ist es sicherer, ein try
um den Versuch herum zu verwenden, es zu öffnen. Beim Überprüfen und anschließenden Öffnen besteht die Gefahr, dass die Datei gelöscht oder verschoben wird oder zwischen dem Überprüfen und dem Versuch, sie zu öffnen.
Wenn Sie nicht vorhaben, die Datei sofort zu öffnen, können Sie sie verwenden os.path.isfile
Rückgabe,
True
wenn der Pfad eine vorhandene reguläre Datei ist. Dies folgt symbolischen Verknüpfungen, sodass sowohl islink () als auch isfile () für denselben Pfad wahr sein können.
import os.path
os.path.isfile(fname)
Wenn Sie sicher sein müssen, dass es sich um eine Datei handelt.
Ab Python 3.4 bietet das pathlib
Modul einen objektorientierten Ansatz (auf pathlib2
Python 2.7 zurückportiert):
from pathlib import Path
my_file = Path("/path/to/file")
if my_file.is_file():
# file exists
Gehen Sie wie folgt vor, um ein Verzeichnis zu überprüfen:
if my_file.is_dir():
# directory exists
Path
Verwenden Sie Folgendes, um zu überprüfen, ob ein Objekt unabhängig davon existiert, ob es sich um eine Datei oder ein Verzeichnis handelt exists()
:
if my_file.exists():
# path exists
Sie können auch resolve(strict=True)
in einem try
Block verwenden:
try:
my_abs_path = my_file.resolve(strict=True)
except FileNotFoundError:
# doesn't exist
else:
# exists
FileNotFoundError
in Python 3 eingeführt wurde. Wenn Sie neben Python 3 auch Python 2.7 unterstützen müssen, können Sie IOError
stattdessen (welche FileNotFoundError
Unterklassen) stackoverflow.com/a/21368457/1960959
open('file', 'r+')
) öffnen und dann bis zum Ende suchen.
Sie haben die os.path.exists
Funktion:
import os.path
os.path.exists(file_path)
Dies gibt True
sowohl für Dateien als auch für Verzeichnisse zurück, aber Sie können stattdessen verwenden
os.path.isfile(file_path)
um zu testen, ob es sich speziell um eine Datei handelt. Es folgen Symlinks.
Im Gegensatz zu isfile()
, exists()
kehrt True
für Verzeichnisse. Je nachdem, ob Sie nur einfache Dateien oder auch Verzeichnisse möchten, verwenden Sie isfile()
oder exists()
. Hier ist eine einfache REPL-Ausgabe:
>>> 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
Verwendung os.path.isfile()
mit 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()
wird false zurückgegeben.
import os
, musst du nicht import os.path
nochmal da es schon ein teil von ist os
. Sie müssen nur importieren, os.path
wenn Sie nur Funktionen von os.path
und nicht von sich os
selbst verwenden möchten, um eine kleinere Sache zu importieren. Wenn Sie jedoch os.access
und verwenden os.R_OK
, wird der zweite Import nicht benötigt.
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
Obwohl fast jeder mögliche Weg in (mindestens einer) der vorhandenen Antworten aufgeführt wurde (z. B. wurde Python 3.4- spezifisches Material hinzugefügt), werde ich versuchen, alles zusammenzufassen.
Hinweis : Jeder Teil des Python- Standardbibliothekscodes, den ich veröffentlichen werde, gehört zur Version 3.5.3 .
Problemstellung :
Mögliche Lösungen :
[Python 3]: os.path. existiert ( Pfad ) (auch andere Funktion Familienmitglieder überprüfen , wie os.path.isfile
, os.path.isdir
, os.path.lexists
für etwas andere Verhaltensweisen)
os.path.exists(path)
Rückgabe,
True
wenn sich der Pfad auf einen vorhandenen Pfad oder einen offenen Dateideskriptor bezieht. GibtFalse
für defekte symbolische Links zurück. Auf einigen Plattformen kann diese Funktion zurückgegeben werden,False
wenn keine Berechtigung zum Ausführen von os.stat () für die angeforderte Datei erteilt wurde , selbst wenn der Pfad physisch vorhanden ist.
Alles gut, aber wenn Sie dem Importbaum folgen:
os.path
- posixpath.py ( ntpath.py )
genericpath.py , Zeile ~ # 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 ist nur ein Try / Except- Block um [Python 3]: os. stat ( Pfad, *, dir_fd = Keine, follow_symlinks = True ) . Ihr Code ist also try / außer free, aber tiefer im Framestack befindet sich (mindestens) ein solcher Block. Dies gilt auch für andere Funktionen ( einschließlich os.path.isfile
).
1.1. [Python 3]: Pfad. is_file ()
Unter der Haube macht es genau das Gleiche ( pathlib.py , Zeile ~ # 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]: Mit Anweisungskontextmanagern . Entweder:
Erstelle einen:
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 ...)
Und seine Verwendung - Ich werde das os.path.isfile
Verhalten replizieren (beachten Sie, dass dies nur zu Demonstrationszwecken dient, versuchen Sie nicht , solchen Code für die Produktion zu schreiben ):
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
Verwenden Sie [Python 3]: contextlib. unterdrücken ( * Ausnahmen ) - wurde speziell zum selektiven Unterdrücken von Ausnahmen entwickelt
Aber sie scheinen Wrapper über try / exception / else / finally- Blöcke zu sein, wie in [Python 3] angegeben: Die with- Anweisung besagt:
Auf diese Weise können allgemeine Versuche ... außer ... schließlich Verwendungsmuster für eine bequeme Wiederverwendung gekapselt werden.
Funktionen zum Durchlaufen des Dateisystems (und Durchsuchen der Ergebnisse nach übereinstimmenden Elementen)
[Python 3]: os. listdir ( path = '.' ) (oder [Python 3]: os. scandir ( path = '.' ) unter Python v 3.5 +, Backport: [PyPI]: scandir )
Unter der Haube verwenden beide:
über [GitHub]: python / cpython - (master) cpython / Modules / posixmodule.c
Die Verwendung von scandir () anstelle von listdir () kann die Leistung von Code erheblich verbessern, der auch Dateityp- oder Dateiattributinformationen benötigt, da os.DirEntry- Objekte diese Informationen verfügbar machen , wenn das Betriebssystem sie beim Scannen eines Verzeichnisses bereitstellt. Alle os.DirEntry- Methoden führen möglicherweise einen Systemaufruf aus, aber is_dir () und is_file () erfordern normalerweise nur einen Systemaufruf für symbolische Links. os.DirEntry.stat () erfordert unter Unix immer einen Systemaufruf, unter Windows jedoch nur einen für symbolische Links.
os.listdir
( os.scandir
sofern verfügbar)glob.glob
)
os.listdir
Da diese Iterierte über Ordner (in den meisten Fällen) sie für unser Problem ineffizient sind (es gibt Ausnahmen, wie nicht wildcarded glob bing - wie @ShadowRanger wies darauf hin), so bin ich nicht auf sie los zu bestehen. Ganz zu schweigen davon, dass in einigen Fällen eine Dateinamenverarbeitung erforderlich sein kann.
[Python 3]: os. Zugang ( Pfad, Modus, *, dir_fd = None, effective_ids = False, follow_symlinks = True ) , dessen Verhalten in der Nähe os.path.exists
(eigentlich ist es weiter, vor allem wegen des 2 nd Arguments)
... testen, ob der aufrufende Benutzer den angegebenen Zugriff auf den Pfad hat . Modus sollte F_OK sein , um die Existenz eines Pfades zu testen ...
os.access("/tmp", os.F_OK)
Da ich in auch Arbeit C , verwende ich diese Methode als auch , weil unter der Haube, ruft es nativen API s (wieder über „$ {} PYTHON_SRC_DIR /Modules/posixmodule.c“ ), aber es eröffnet auch ein Tor für mögliche Benutzer Fehler , und es ist nicht so Python ic wie andere Varianten. Verwenden Sie es also, wie @AaronHall zu Recht betont hat, nur, wenn Sie wissen, was Sie tun:
Hinweis : Das Aufrufen nativer APIs ist auch über [Python 3] möglich: ctypes - Eine Fremdfunktionsbibliothek für Python , in den meisten Fällen jedoch komplizierter.
( Win- spezifisch): Da vcruntime * ( msvcr * ) .dll eine [MS.Docs] exportiert : _access, _waccess- Funktionsfamilie ebenfalls, hier ein Beispiel:
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
Anmerkungen :
os.F_OK
im Aufruf, aber das dient nur der Klarheit (der Wert ist 0 ).
Das Gegenstück zu Lnx ( Ubtu (16 x 64) ):
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
Anmerkungen :
Statt hartzucodieren libc ‚s Pfad ( ‚/lib/x86_64-linux-gnu/libc.so.6‘ ) , die kann (und wahrscheinlich wird) über Systeme variieren, keine (oder die leere Zeichenkette) kann übergeben werden CDLL Konstruktor ( ctypes.CDLL(None).access(b"/tmp", os.F_OK)
). Nach [man7]: DLOPEN (3) :
Wenn der Dateiname NULL ist, gilt das zurückgegebene Handle für das Hauptprogramm. Wenn dieses Handle an dlsym () übergeben wird, wird im Hauptprogramm nach einem Symbol gesucht, gefolgt von allen gemeinsam genutzten Objekten, die beim Programmstart geladen wurden, und allen gemeinsam genutzten Objekten, die von dlopen () mit dem Flag RTLD_GLOBAL geladen wurden .
__declspec(dllexport)
(warum um alles in der Welt würde die normale Person das tun?), das Hauptprogramm ist ladbar, aber ziemlich unbrauchbarInstallieren Sie ein Modul eines Drittanbieters mit Dateisystemfunktionen
Wird sich höchstwahrscheinlich auf einen der oben genannten Wege stützen (möglicherweise mit geringfügigen Anpassungen).
Ein Beispiel wäre (wieder Win- spezifisch) [GitHub]: mhammond / pywin32 - Python für Windows (pywin32) Extensions , ein Python- Wrapper über WINAPIs .
Aber da dies eher eine Problemumgehung ist, höre ich hier auf.
Eine andere (lahme) Problemumgehung ( Gainarie ) ist (wie ich es gerne nenne) der Sysadmin- Ansatz: Verwenden Sie Python als Wrapper, um Shell-Befehle auszuführen
Gewinnen :
(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
Fazit :
Schlussbemerkung (en) :
glob.iglob
(und glob.glob
auch) basieren aufos.scandir
, also ist es jetzt faul; Um den ersten Treffer in einem Verzeichnis mit 10 Millionen Dateien zu erhalten, scannen Sie nur, bis Sie den ersten Treffer erreichen. Und selbst vor Version 3.6 ist glob
die Funktion intelligent , wenn Sie Methoden ohne Platzhalter verwenden: Sie weiß, dass Sie nur einen Treffer erzielenos.path.isdir
os.path.lexists
können, und vereinfacht das Globbing auf nur oder (je nachdem, ob der Pfad endet /
).
os.path.isdir
oder os.path.lexist
da es sich um eine Reihe von Funktionsaufrufen und Zeichenfolgen auf Python-Ebene handelt Operationen, bevor entschieden wird, dass der effiziente Pfad realisierbar ist, aber kein zusätzlicher Systemaufruf oder E / A-Arbeit (um Größenordnungen langsamer).
Dies ist der einfachste Weg, um zu überprüfen, ob eine Datei vorhanden ist. Nur weil die Datei bei der Überprüfung vorhanden war, kann nicht garantiert werden, dass sie beim Öffnen vorhanden ist.
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+ verfügt über ein objektorientiertes Pfadmodul : pathlib . Mit diesem neuen Modul können Sie überprüfen, ob eine Datei wie folgt vorhanden ist:
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
Sie können (und sollten normalerweise) try/except
beim Öffnen von Dateien weiterhin einen Block verwenden:
try:
with p.open() as f:
# do awesome stuff
except OSError:
print('Well darn.')
Das pathlib-Modul enthält viele coole Dinge: bequemes Globbing, Überprüfen des Dateibesitzers, einfacheres Verbinden von Pfaden usw. Es lohnt sich, es sich anzusehen. Wenn Sie mit einem älteren Python (Version 2.6 oder höher) arbeiten, können Sie pathlib weiterhin mit pip installieren:
# installs pathlib2 on older Python versions
# the original third-party module, pathlib, is no longer maintained.
pip install pathlib2
Importieren Sie es dann wie folgt:
# Older Python versions
import pathlib2 as pathlib
Bevorzugen Sie die try-Anweisung. Es gilt als besserer Stil und vermeidet Rennbedingungen.
Nimm mein Wort nicht dafür. Es gibt viel Unterstützung für diese Theorie. Hier ist ein paar:
try...except
hilft ohnehin nicht, dieses Problem zu lösen .
except:
Klausel dazu führt, dass eine in diesem Teil Ihres Codes auftretende Ausnahme eine verwirrende Meldung auslöst (zweiter Fehler während die Verarbeitung des ersten.)
Wie überprüfe ich mithilfe von Python, ob eine Datei vorhanden ist, ohne eine try-Anweisung zu verwenden?
Jetzt seit Python 3.4 verfügbar, importieren und instanziieren Sie ein Path
Objekt mit dem Dateinamen und überprüfen Sie die is_file
Methode (beachten Sie, dass dies True für Symlinks zurückgibt, die auch auf reguläre Dateien verweisen):
>>> from pathlib import Path
>>> Path('/').is_file()
False
>>> Path('/initrd.img').is_file()
True
>>> Path('/doesnotexist').is_file()
False
Wenn Sie mit Python 2 arbeiten, können Sie das pathlib-Modul von pypi aus zurückportieren pathlib2
oder auf andere Weise isfile
vom Modul aus überprüfen os.path
:
>>> import os
>>> os.path.isfile('/')
False
>>> os.path.isfile('/initrd.img')
True
>>> os.path.isfile('/doesnotexist')
False
Das Obige ist hier wahrscheinlich die beste pragmatische direkte Antwort, aber es besteht die Möglichkeit einer Race-Bedingung (abhängig davon, was Sie erreichen möchten) und die Tatsache, dass die zugrunde liegende Implementierung a verwendet try
, Python jedoch verwendettry
überall in ihrer Implementierung verwendet.
Weil Python verwendet try
überall verwendet wird, gibt es wirklich keinen Grund, eine Implementierung zu vermeiden, die es verwendet.
Der Rest dieser Antwort versucht jedoch, diese Vorbehalte zu berücksichtigen.
Verwenden Sie das neue Path
Objekt in Python 3.4 pathlib
. Beachten Sie, dass dies .exists
nicht ganz richtig ist, da Verzeichnisse keine Dateien sind (außer im Unix-Sinne, dass alles eine Datei ist).
>>> from pathlib import Path
>>> root = Path('/')
>>> root.exists()
True
Also müssen wir verwenden is_file
:
>>> root.is_file()
False
Hier ist die Hilfe zu is_file
:
is_file(self)
Whether this path is a regular file (also True for symlinks pointing
to regular files).
Holen wir uns also eine Datei, von der wir wissen, dass sie eine Datei ist:
>>> import tempfile
>>> file = tempfile.NamedTemporaryFile()
>>> filepathobj = Path(file.name)
>>> filepathobj.is_file()
True
>>> filepathobj.exists()
True
Standardmäßig wird NamedTemporaryFile
die Datei beim Schließen gelöscht (und automatisch geschlossen, wenn keine weiteren Verweise darauf vorhanden sind).
>>> del file
>>> filepathobj.exists()
False
>>> filepathobj.is_file()
False
Wenn Sie sich vertiefen der Implementierung befassen, werden Sie feststellen, dass is_file
Folgendes verwendet wird 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
Wir mögen, try
weil es Rennbedingungen vermeidet. Mit try
versuchen Sie einfach, Ihre Datei zu lesen, und erwarten, dass sie dort vorhanden ist. Wenn nicht, fangen Sie die Ausnahme ab und führen das Fallback-Verhalten aus, das sinnvoll ist.
Wenn Sie überprüfen möchten, ob eine Datei vorhanden ist, bevor Sie versuchen, sie zu lesen, und Sie sie möglicherweise löschen und dann möglicherweise mehrere Threads oder Prozesse verwenden oder ein anderes Programm diese Datei kennt und sie löschen könnte, besteht die Gefahr, dass dies der Fall ist eine Rennbedingung wenn Sie überprüfen, ob sie vorhanden ist, weil Sie dann versuchen , sie vor ihrer Bedingung zu öffnen (ihre Existenz) ändert.
Die Rennbedingungen sind sehr schwer zu debuggen, da es ein sehr kleines Fenster gibt, in dem Ihr Programm fehlschlagen kann.
Aber wenn dies Ihre Motivation, Sie können Sie den Wert einer try
Aussage mithilfe von ermittelnsuppress
Kontextmanagers ermitteln.
suppress
Python 3.4 gibt uns den suppress
Kontextmanager (früher der ignore
Kontextmanager), der in weniger Zeilen semantisch genau dasselbe tut und gleichzeitig (zumindest oberflächlich) die ursprüngliche Aufforderung erfüllt, eine try
Aussage zu vermeiden :
from contextlib import suppress
from pathlib import Path
Verwendungszweck:
>>> with suppress(OSError), Path('doesnotexist').open() as f:
... for line in f:
... print(line)
...
>>>
>>> with suppress(OSError):
... Path('doesnotexist').unlink()
...
>>>
Für frühere Pythons könnten Sie Ihre eigenen würfeln suppress
, aber ohne a try
wird es ausführlicher als mit. Ich glaube, dies ist tatsächlich die einzige Antwort, die try
auf keiner Ebene in Python verwendet wird und auf die vor Python 3.4 angewendet werden kann, da stattdessen ein Kontextmanager verwendet wird:
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)
Vielleicht einfacher mit einem Versuch:
from contextlib import contextmanager
@contextmanager
def suppress(*exceptions):
try:
yield
except exceptions:
pass
isfile
import os
os.path.isfile(path)
aus den Dokumenten :
os.path.isfile(path)
Geben Sie True zurück, wenn der Pfad eine vorhandene reguläre Datei ist. Dies folgt symbolischen Verknüpfungen, also beides
islink()
undisfile()
kann für denselben Pfad zutreffen.
Wenn Sie jedoch die Quelle dieser Funktion untersuchen, werden Sie feststellen, dass tatsächlich eine try-Anweisung verwendet wird:
# 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
Alles, was es tut, ist, den angegebenen Pfad zu verwenden, um zu sehen, ob Statistiken darauf abgerufen werden können, abzufangen OSError
und dann zu überprüfen, ob es sich um eine Datei handelt, wenn die Ausnahme nicht ausgelöst wurde.
Wenn Sie beabsichtigen, etwas mit der Datei zu tun, würde ich vorschlagen, es direkt mit einem Versuch zu versuchen - außer um eine Rennbedingung zu vermeiden:
try:
with open(path) as f:
f.read()
except OSError:
pass
os.access
Verfügbar für Unix und Windows ist os.access
, aber um zu verwenden, müssen Sie Flags übergeben, und es wird nicht zwischen Dateien und Verzeichnissen unterschieden. Dies wird eher verwendet, um zu testen, ob der tatsächlich aufrufende Benutzer Zugriff in einer Umgebung mit erhöhten Berechtigungen hat:
import os
os.access(path, os.F_OK)
Es leidet auch unter den gleichen Problemen mit den Rennbedingungen wie isfile
. Aus den Dokumenten :
Hinweis: Wenn Sie mit access () prüfen, ob ein Benutzer berechtigt ist, z. B. eine Datei zu öffnen, bevor Sie dies tatsächlich mit open () tun, entsteht eine Sicherheitslücke, da der Benutzer möglicherweise das kurze Zeitintervall zwischen dem Überprüfen und Öffnen der Datei ausnutzt, um sie zu bearbeiten. Es ist vorzuziehen, EAFP-Techniken zu verwenden. Zum Beispiel:
if os.access("myfile", os.R_OK): with open("myfile") as fp: return fp.read() return "some default data"
ist besser geschrieben als:
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()
Vermeide das Benutzen os.access
. Es handelt sich um eine Funktion auf niedriger Ebene, die mehr Möglichkeiten für Benutzerfehler bietet als die oben diskutierten Objekte und Funktionen auf höherer Ebene.
Eine andere Antwort sagt dies über os.access
:
Persönlich bevorzuge ich dieses, weil es unter der Haube native APIs aufruft (über "$ {PYTHON_SRC_DIR} /Modules/posixmodule.c"), aber es öffnet auch ein Tor für mögliche Benutzerfehler und es ist nicht so pythonisch wie andere Varianten ::
Diese Antwort besagt, dass eine nicht pythonische, fehleranfällige Methode ohne Rechtfertigung bevorzugt wird. Es scheint Benutzer zu ermutigen, APIs auf niedriger Ebene zu verwenden, ohne sie zu verstehen.
Außerdem wird ein Kontextmanager erstellt, der durch bedingungslose Rückgabe True
alle Ausnahmen (einschließlich KeyboardInterrupt
und SystemExit
!) Im Stillen passieren lässt. Dies ist eine gute Möglichkeit, Fehler zu verbergen.
Dies scheint die Benutzer zu ermutigen, schlechte Praktiken anzuwenden.
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!"
Das Importieren os
erleichtert das Navigieren und Ausführen von Standardaktionen mit Ihrem Betriebssystem.
Als Referenz siehe auch Überprüfen, ob eine Datei mit Python vorhanden ist.
Wenn Sie Operationen auf hoher Ebene benötigen, verwenden Sie shutil
.
os.path.exists
Gibt true für Dinge zurück, die keine Dateien sind, z. B. Verzeichnisse. Dies ergibt falsch positive Ergebnisse. Siehe die anderen Antworten, die empfehlen os.path.isfile
.
Testen auf Dateien und Ordner mit os.path.isfile()
, os.path.isdir()
undos.path.exists()
Unter der Annahme, dass der "Pfad" ein gültiger Pfad ist, zeigt diese Tabelle, was von jeder Funktion für Dateien und Ordner zurückgegeben wird:
Sie können auch testen, ob eine Datei ein bestimmter Dateityp ist os.path.splitext()
, um die Erweiterung zu erhalten (falls Sie sie noch nicht kennen).
>>> 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
Im Jahr 2016 ist der beste Weg immer noch os.path.isfile
:
>>> os.path.isfile('/path/to/some/file.txt')
Oder in Python 3 können Sie Folgendes verwenden pathlib
:
import pathlib
path = pathlib.Path('/path/to/some/file.txt')
if path.is_file():
...
pathlib
ist die OOP-Lösung von Python für Pfade. Sie können viel mehr damit machen. Wenn Sie nur die Existenz überprüfen müssen, ist der Vorteil nicht so groß.
Es scheint nicht so, als gäbe es einen bedeutenden funktionalen Unterschied zwischen try / without und isfile()
, also sollten Sie verwenden, welches sinnvoll ist.
Wenn Sie eine Datei lesen möchten, falls vorhanden, tun Sie dies
try:
f = open(filepath)
except IOError:
print 'Oh dear.'
Wenn Sie eine Datei jedoch nur umbenennen möchten, wenn sie vorhanden ist, und sie daher nicht öffnen müssen, tun Sie dies
if os.path.isfile(filepath):
os.rename(filepath, filepath + '.old')
Wenn Sie in eine Datei schreiben möchten, falls diese nicht vorhanden ist, tun Sie dies
# 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'
Wenn Sie eine Dateisperrung benötigen, ist das eine andere Sache.
os.path.exists
Gibt true für Dinge zurück, die keine Dateien sind, z. B. Verzeichnisse. Dies ergibt falsch positive Ergebnisse. Siehe die anderen Antworten, die empfehlen os.path.isfile
.
filepath
mit dem richtigen Timing, und BAM überschreibt die Zieldatei. Sie sollten dies open(filepath, 'wx')
in einem try...except
Block tun , um das Problem zu vermeiden.
OSError
falls filepath + '.old'
bereits vorhanden: "Unter Windows wird, wenn dst bereits vorhanden ist, OSError ausgelöst, auch wenn es sich um eine Datei handelt. Es gibt möglicherweise keine Möglichkeit, eine atomare Umbenennung bei dst zu implementieren benennt eine vorhandene Datei. "
os.replace
Zieldatei portabel stumm ersetzt (identisch mit os.rename
dem Linux-Verhalten) (es treten nur Fehler auf, wenn der Zielname vorhanden ist und ein Verzeichnis ist). Sie stecken also auf 2.x fest, aber Py3-Benutzer haben seit einigen Jahren eine gute Option.
rename
Beispiel: Es sollte immer noch mit try
/ gemacht werden except
. os.rename
(oder os.replace
auf modernem Python) ist atomar; Wenn Sie es überprüfen und dann umbenennen, werden unnötige Rennen und zusätzliche Systemaufrufe ausgeführt. Tun try: os.replace(filepath, filepath + '.old') except OSError: pass
Sie könnten dies versuchen (sicherer):
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))
Die Ausgabe wäre:
([Errno 2] Keine solche Datei oder kein solches Verzeichnis: 'Whatever.txt')
Abhängig vom Ergebnis kann Ihr Programm dann einfach von dort aus weiter ausgeführt werden, oder Sie können Code verwenden, um es zu stoppen, wenn Sie möchten.
try
Obwohl ich immer die Verwendung von try
und except
Aussagen empfehle , sind hier einige Möglichkeiten für Sie (mein persönlicher Favorit ist die Verwendung os.access
):
Versuchen Sie, die Datei zu öffnen:
Durch das Öffnen der Datei wird immer die Existenz der Datei überprüft. Sie können eine Funktion wie folgt erstellen:
def File_Existence(filepath):
f = open(filepath)
return True
Wenn es falsch ist, wird die Ausführung mit einem nicht übergebenen IOError oder OSError in späteren Versionen von Python gestoppt. Um die Ausnahme abzufangen, müssen Sie eine try Except-Klausel verwenden. Natürlich können Sie immer eine try
Ausnahme-Anweisung wie diese verwenden (danke an hsandt
, der mich zum Nachdenken gebracht hat):
def File_Existence(filepath):
try:
f = open(filepath)
except IOError, OSError: # Note OSError is for later versions of Python
return False
return True
Verwendung os.path.exists(path)
:
Dadurch wird die Existenz Ihrer Angaben überprüft. Es wird jedoch nach Dateien und Verzeichnissen gesucht. Achten Sie daher darauf, wie Sie es verwenden.
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
Verwendung os.access(path, mode)
:
Dadurch wird geprüft, ob Sie Zugriff auf die Datei haben. Es wird nach Berechtigungen gesucht. Basierend auf der os.py-Dokumentation wird beim Eingeben os.F_OK
die Existenz des Pfads überprüft. Wenn Sie dies verwenden, entsteht jedoch eine Sicherheitslücke, da jemand Ihre Datei in der Zeit zwischen dem Überprüfen der Berechtigungen und dem Öffnen der Datei angreifen kann. Sie sollten stattdessen direkt zum Öffnen der Datei gehen, anstatt deren Berechtigungen zu überprüfen. ( EAFP gegen LBYP ). Wenn Sie die Datei anschließend nicht öffnen und nur ihre Existenz überprüfen möchten, können Sie diese verwenden.
Wie auch immer, hier:
>>> import os
>>> os.access("/is/a/file.txt", os.F_OK)
True
Ich sollte auch erwähnen, dass es zwei Möglichkeiten gibt, wie Sie die Existenz einer Datei nicht überprüfen können. Entweder wird das Problem sein permission denied
oder no such file or directory
. Wenn Sie eine fangen IOError
, setzen Sie die IOError as e
(wie meine erste Option) und geben Sie sie ein , print(e.args)
damit Sie hoffentlich Ihr Problem feststellen können. Ich hoffe, es hilft! :) :)
Datum: 2017-12-04
Jede mögliche Lösung wurde in anderen Antworten aufgeführt.
Eine intuitive und streitbare Möglichkeit, um zu überprüfen, ob eine Datei vorhanden ist, ist die folgende:
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')
Ich habe ein ausführliches Cheatsheet als Referenz erstellt:
#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']}
Wenn die Datei geöffnet werden soll, können Sie eine der folgenden Techniken verwenden:
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!')
AKTUALISIEREN
Um Verwirrung zu vermeiden und basierend auf den Antworten, die ich erhalten habe, findet die aktuelle Antwort entweder eine Datei oder ein Verzeichnis mit dem angegebenen Namen.
os.path.exists
Gibt true für Dinge zurück, die keine Dateien sind, z. B. Verzeichnisse. Dies ergibt falsch positive Ergebnisse. Siehe die anderen Antworten, die empfehlen 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"
Das Auslösen von Ausnahmen wird als akzeptabler und pythonischer Ansatz für die Flusskontrolle in Ihrem Programm angesehen. Ziehen Sie in Betracht, fehlende Dateien mit IOErrors zu behandeln. In dieser Situation wird eine IOError-Ausnahme ausgelöst, wenn die Datei vorhanden ist, der Benutzer jedoch keine Leseberechtigungen hat.
Sie können Brians Vorschlag ohne die schreiben try:
.
from contextlib import suppress
with suppress(IOError), open('filename'):
process()
suppress
ist Teil von Python 3.4. In älteren Releases können Sie schnell Ihre eigene Unterdrückung schreiben:
from contextlib import contextmanager
@contextmanager
def suppress(*exceptions):
try:
yield
except exceptions:
pass
Ich bin der Autor eines Pakets, das es seit ungefähr 10 Jahren gibt, und es hat eine Funktion, die diese Frage direkt anspricht. Wenn Sie sich auf einem Nicht-Windows-System befinden, wird Popen
der Zugriff verwendet find
. Wenn Sie jedoch unter Windows arbeiten, wird es repliziertfind
mit einem effizienten Dateisystem-Walker .
Der Code selbst verwendet keinen try
Block… außer um das Betriebssystem zu bestimmen und Sie so zum "Unix" -Stil find
oder zum Hand-Buillt zu führen find
. Timing-Tests zeigten, dass das try
Betriebssystem schneller ermittelt werden konnte, daher habe ich dort eines verwendet (aber nirgendwo anders).
>>> import pox
>>> pox.find('*python*', type='file', root=pox.homedir(), recurse=False)
['/Users/mmckerns/.python']
Und der 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']
>>>
Die Implementierung finden Sie hier: https://github.com/uqfoundation/pox/blob/89f90fb308f285ca7a62eabe2c38acb87e89dad9/pox/shutils.py#L190
Sie können diesen drei Möglichkeiten folgen:
Hinweis 1: Wird
os.path.isfile
nur für Dateien verwendet
import os.path
os.path.isfile(filename) # True if file exists
os.path.isfile(dirname) # False if directory exists
Hinweis 2: Wird
os.path.exists
sowohl für Dateien als auch für Verzeichnisse verwendet
import os.path
os.path.exists(filename) # True if file exists
os.path.exists(dirname) #True if directory exists
Die
pathlib.Path
Methode (in Python 3+ enthalten, mit pip für Python 2 installierbar)
from pathlib import Path
Path(filename).exists()
Hinzufügen einer weiteren geringfügigen Variation, die sich in den anderen Antworten nicht genau widerspiegelt.
Dies behandelt den Fall des file_path
Seins None
oder der leeren Zeichenfolge.
def file_exists(file_path):
if not file_path:
return False
elif not os.path.isfile(file_path):
return False
else:
return True
Hinzufügen einer Variante auf Vorschlag von Shahbaz
def file_exists(file_path):
if not file_path:
return False
else:
return os.path.isfile(file_path)
Hinzufügen einer Variante auf Vorschlag von Peter Wood
def file_exists(file_path):
return file_path and os.path.isfile(file_path):
if (x) return true; else return false;
ist wirklich gerecht return x
. Ihre letzten vier Zeilen können werden return os.path.isfile(file_path)
. Während wir gerade dabei sind, kann die gesamte Funktion als vereinfacht werden return file_path and os.path.isfile(file_path)
.
return x
im Fall von vorsichtig sein if (x)
. Python betrachtet eine leere Zeichenfolge als falsch. In diesem Fall würden wir eine leere Zeichenfolge anstelle eines Bools zurückgeben. Der Zweck dieser Funktion ist es, immer bool zurückzugeben.
x
ist os.path.isfile(..)
es jedoch so, dass es schon bool ist.
os.path.isfile(None)
löst eine Ausnahme aus, weshalb ich den if-Check hinzugefügt habe. Ich könnte es wahrscheinlich einfach in einen Versuch einwickeln / außer stattdessen, aber ich fand, dass es auf diese Weise expliziter war.
return file_path and os.path.isfile(file_path)
Hier ist ein 1-zeiliger Python-Befehl für die Linux-Befehlszeilenumgebung. Ich finde das SEHR HANDY, da ich kein so heißer Bash-Typ bin.
python -c "import os.path; print os.path.isfile('/path_to/file.xxx')"
Ich hoffe das ist hilfreich.
[ -f "${file}" ] && echo "file found" || echo "file not found"
(entspricht if [ ... ]; then ...; else ...; fi
).
Sie können die "OS" -Bibliothek von Python verwenden:
>>> import os
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.txt")
True
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.tx")
False
os.path.exists
Gibt true für Dinge zurück, die keine Dateien sind, z. B. Verzeichnisse. Dies ergibt falsch positive Ergebnisse. Siehe die anderen Antworten, die empfehlen os.path.isfile
.
exists
ist dies in Ordnung. Wenn das Ziel darin besteht, festzustellen, ob es sicher ist, eine vermutlich vorhandene Datei zu öffnen, ist die Kritik berechtigt und nicht präzise genug. Leider gibt das OP nicht an, welches das gewünschte Ziel ist (und wird dies wahrscheinlich nicht mehr tun).
Wie überprüfe ich, ob eine Datei vorhanden ist, ohne die try-Anweisung zu verwenden?
Im Jahr 2016 ist dies wohl immer noch der einfachste Weg, um zu überprüfen, ob sowohl eine Datei vorhanden ist als auch ob es sich um eine Datei handelt:
import os
os.path.isfile('./file.txt') # Returns True if exists, else False
isfile
ist eigentlich nur eine Hilfsmethode, die intern os.stat
und stat.S_ISREG(mode)
darunter verwendet wird. Dies os.stat
ist eine untergeordnete Methode, mit der Sie detaillierte Informationen zu Dateien, Verzeichnissen, Sockets, Puffern und mehr erhalten. Mehr über os.stat hier
Hinweis: Dieser Ansatz sperrt die Datei jedoch in keiner Weise und daher kann Ihr Code anfällig für TOCTTOU- Fehler ( Time of Check to Time of Use ) werden.
Das Auslösen von Ausnahmen wird daher als akzeptabler und pythonischer Ansatz für die Flusskontrolle in Ihrem Programm angesehen. Und man sollte in Betracht ziehen, fehlende Dateien mit IOErrors zu behandeln, anstatt if
Anweisungen ( nur ein Ratschlag ).
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)
wird zurückgegeben, True
wenn die Datei vom Prozess \ program \ thread