Frage Wie überprüfe ich, ob eine Datei existiert?


Wie sehe ich, ob eine Datei existiert oder nicht, ohne die try Erklärung?


4347
2017-09-17 12:55


Ursprung


Antworten:


Wenn der Grund, den Sie überprüfen, so ist, können Sie etwas wie tun if file_exists: open_it()Es ist sicherer, einen zu verwenden try um den Versuch, es zu öffnen. Das Überprüfen und anschließende Öffnen birgt das Risiko, dass die Datei gelöscht oder verschoben wird oder etwas zwischen dem Zeitpunkt der Überprüfung und dem Versuch, sie zu öffnen.

Wenn Sie nicht planen, die Datei sofort zu öffnen, können Sie sie verwenden os.path.isfile

Rückkehr True Wenn Pfad eine vorhandene reguläre Datei ist. Dies folgt symbolischen Verbindungen, also beides islink () und Isdatei () kann für den gleichen Weg wahr sein.

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

wenn Sie sicher sein müssen, dass es eine Datei ist.

Beginnend mit Python 3.4, der pathlib Modul bietet einen objektorientierten Ansatz (rückportiert nach pathlib2 in Python 2.7):

from pathlib import Path

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

Um ein Verzeichnis zu überprüfen, tun Sie Folgendes:

if my_file.is_dir():
    # directory exists

Um zu überprüfen, ob a Path Objekt existiert unabhängig davon, ob es sich um eine Datei oder ein Verzeichnis handelt, verwenden exists():

if my_file.exists():
    # path exists

Sie können auch verwenden resolve() in einem try Block:

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

3949
2017-09-17 12:57



Du hast die os.path.exists Funktion:

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

Dies kehrt zurück True für beide Dateien und Verzeichnisse, aber Sie können stattdessen verwenden

os.path.isfile(file_name)

um zu testen, ob es sich um eine Datei handelt. Es folgt Symlinks.


1624
2017-09-17 12:57



nicht wie isfile(), exists() wird zurückkehren True für Verzeichnisse.
Also abhängig davon, ob du nur einfache Dateien oder auch Verzeichnisse willst, wirst du verwenden isfile() oder exists(). Hier ist ein einfacher REPL-Ausgang.

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

835
2017-09-17 15:01



import os.path

if os.path.isfile(filepath):

467
2017-09-17 12:55



Benutzen os.path.isfile() mit os.access():

import os
import os.path

PATH='./file.txt'

if os.path.isfile(PATH) and os.access(PATH, os.R_OK):
    print "File exists and is readable"
else:
    print "Either the file is missing or not readable"

220
2018-01-16 05:57



import os
os.path.exists(path) # Returns whether the path (directory or file) exists or not
os.path.isfile(path) # Returns whether the file exists or not

209
2017-09-17 12:56



Dies ist der einfachste Weg zu überprüfen, ob eine Datei existiert. Gerade weil Die Datei existiert, wenn Sie nicht geprüft haben Garantie dass es da sein wird, wenn du es öffnen musst.

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:

Obwohl fast jeder mögliche Weg in (mindestens eine) der existierenden Antworten aufgelistet ist (z.B. Python 3.4 bestimmte Sachen wurden hinzugefügt), ich werde versuchen, alles zusammen zu gruppieren.

Hinweis: jedes Stück von Python Standard-Bibliothekscode, den ich posten werde, gehört zur Version 3.5.3 (Doc-Anführungszeichen sind Version 3 Spezifisch).

Problemstellung:

  1. Datei prüfen (diskutierbar: auch Ordner ("spezielle" Datei)?) Existenz
  2. Benutze es nicht try / except / else / finally Blöcke

Mögliche Lösungen:

  1. [Python]: os.pfad.existiert(Pfad) (Überprüfen Sie auch andere Funktionsfamilienmitglieder wie os.path.isfile, os.path.isdir, os.path.lexists für etwas anderes Verhalten)

    os.path.exists(path)
    

    Rückkehr True ob Pfad verweist auf einen vorhandenen Pfad oder einen geöffneten Dateideskriptor. Kehrt zurück False für gebrochene symbolische Links. Auf einigen Plattformen kann diese Funktion zurückkehren False wenn die Berechtigung zum Ausführen nicht erteilt wird os.stat () auf der angeforderten Datei, auch wenn die Pfad physisch existiert.

    Alles gut, aber wenn man dem Importbaum folgt:

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

      • genericpath.py, Linie ~ # 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 herumblocken [Python]: os.stat(path, *, dir_fd = Keine, follow_symlinks = True). Also, dein Code ist try/except frei, aber niedriger im Frame-Stack gibt es (zumindest) ein solcher Block. Dies gilt auch für andere Funktionen (einschließlich  os.path.isfile).

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

    • Es ist ein Züchter (und mehr Pythonic) Art der Behandlung von Pfaden, aber
    • Unter der Haube tut es das genau das gleiche (pfadlib.py, Linie ~ # 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]: 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 repliziere die isfile Verhalten (beachten Sie, dass dies nur für Demonstrationszwecke ist, tun Sie nicht Versuchen Sie, solchen Code zu schreiben Produktion):

        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
        
    • Benutzen [Python]: Kontextbibliothek.unterdrücken(* Ausnahmen) - Was war speziell entworfen für die selektive Unterdrückung von Ausnahmen


    Aber es scheint, als seien sie umhüllt try/except/else/finally Blöcke, als [Python]: Die mit Erklärung Zustände:

    Dies ermöglicht eine gemeinsame Versuchen...außer...endlich Verwendungsmuster, die zur bequemen Wiederverwendung eingekapselt werden.

  3. Dateisystem-Traversierungsfunktionen (und suchen die Ergebnisse nach übereinstimmenden Elementen)


    Da diese über Ordner laufen (in den meisten Fällen), sind sie für unser Problem ineffizient (es gibt Ausnahmen, wie z. B. nicht verwaiste) globbing - wie @ShadowRanger darauf hingewiesen hat, also werde ich nicht auf ihnen bestehen. Ganz zu schweigen davon, dass in einigen Fällen die Verarbeitung von Dateinamen erforderlich sein kann.

  4. [Python]: os.Zugriff(Pfad, Modus, *, dir_fd = Keine, effektive_ID = False, follow_symlinks = True) dessen Verhalten nahe ist os.path.exists (eigentlich ist es breiter, hauptsächlich wegen der 2nd Streit)

    • Benutzerberechtigungen könnte die Datei "Sichtbarkeit" einschränken, wie das Dokument sagt:

      ... testen, ob der aufrufende Benutzer den angegebenen Zugriff hat Pfad. Modus sollte sein F_OK um die Existenz von Pfad zu testen ...

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

    Da arbeite ich auch in C, Ich benutze diese Methode auch, weil unter der Haube, ruft es einheimisch APIs (wieder via "$ {PYTHON_SRC_DIR} /Module/posixmodule.c"), aber es öffnet auch ein Tor für möglich Benutzerfehlerund es ist nicht so Pythonic wie andere Varianten. Also, wie @AaronHall zu Recht angemerkt hat, benutze es nur, wenn du weißt, was du tust:

    Hinweis: Native aufrufen APIs ist auch über möglich [Python]: Ctypes - Eine Fremdfunktionsbibliothek für Python, aber in den meisten Fällen ist es komplizierter.

    (Sieg spezifisch): Seit msvcr *(vcruntime *) exportiert a [MSDN]: _access, _waccess Funktionsfamilie, 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", os.F_OK)
    -1
    

    Anmerkungen:

    • Obwohl es keine gute Übung ist, benutze ich os.F_OK im Anruf, aber das ist nur für die Klarheit (sein Wert ist 0)
    • Ich benutze _waccess damit der gleiche Code funktioniert Python3 und Python2 (trotz Unicode verwandte Unterschiede zwischen ihnen)
    • Obwohl dies ein sehr spezifisches Gebiet betrifft, Es wurde in keiner der vorherigen Antworten erwähnt


    Das Lnx (Ubtu (16 x64)) Gegenstück auch:

    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
    

    Anmerkungen:

    • Statt Hardcoding libc's Weg ("/lib/x86_64-linux-gnu/libc.so.6") welche sich (und wahrscheinlich auch) über die Systeme hinweg verändern können, None (oder die leere Zeichenfolge) kann übergeben werden CDLL Konstrukteur (ctypes.CDLL(None).access(b"/tmp", os.F_OK)). Gemäß [Mann]: DLOPEN (3):

      Ob Dateiname ist NULL, dann ist das zurückgegebene Handle für das Main   Programm. Wenn gegeben zu dlsym(), dieser Handle verursacht eine Suche nach einem   Symbol im Hauptprogramm, gefolgt von allen geteilten Objekten, die geladen werden   Programmstart und dann alle gemeinsam genutzten Objekte geladen von dlopen() mit   die Flagge RTLD_GLOBAL.

      • Main (aktuelles) Programm (Python) ist dagegen verlinkt libc, so seine Symbole (einschließlich access) wird geladen
      • Dies muss mit Vorsicht behandelt werden, da Funktionen wie main, Py_Main und (alle) anderen sind verfügbar; sie anzurufen, könnte katastrophale Auswirkungen haben (auf das aktuelle Programm)
      • Dies gilt nicht auch für Sieg (Aber das ist nicht so eine große Sache, seit msvcrt.dllbefindet sich in "% SystemRoot% \ System32" welches ist in %PFAD% standardmäßig). Ich wollte die Dinge weiter treiben und dieses Verhalten wiederholen Sieg (und einen Patch einreichen), aber wie sich herausstellt, [MSDN]: GetProcAddress-Funktion nur "sieht" exportiert Symbole, wenn nicht jemand die Funktionen in der Hauptdatei als deklariert __declspec(dllexport) (Warum auf der Erde regulär Person würde das tun?), das Hauptprogramm ist ladbar, aber ziemlich unbrauchbar
  5. Installieren Sie einige 3rd Party-Modul mit Dateisystem-Fähigkeiten

    Höchstwahrscheinlich wird sich auf eine der oben genannten Möglichkeiten verlassen (vielleicht mit leichten Anpassungen).
    Ein Beispiel wäre Sieg Spezifisch) [GitHub]: Python für Windows (pywin32) Erweiterungen, die ein Python Wrapper über WINAPIs.

    Aber da dies eher ein Workaround ist, halte ich hier an.

  6. Eine andere (lahme) Problemumgehung (Gainarie) ist (wie ich es gerne nenne) Systemadministrator Ansatz: verwenden Python als Wrapper zum Ausführen von Shell-Befehlen

    • Sieg:

      (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
      

Endeffekt:

  • Machen benutzen try / except / else / finally Blöcke, weil sie verhindern können, dass Sie in eine Reihe von unangenehmen Problemen geraten. Ein Gegenbeispiel, das mir einfällt, ist die Leistung: Solche Blöcke sind teuer, also versuchen Sie, sie nicht in Code zu platzieren, der Hunderttausende von Malen pro Sekunde ausführen soll (aber da es in den meisten Fällen Festplattenzugriffe gibt), es wird nicht der Fall sein).

Schlussnote (n):

  • Ich werde versuchen, es auf dem Laufenden zu halten, irgendwelche Vorschläge sind willkommen, ich werde irgendetwas Nützliches einbeziehen, das in der Antwort auftauchen wird

136
2018-06-20 19:28