[Python] Wie überprüfe ich, ob eine Datei existiert?


Answers

Sie haben die Funktion os.path.exists :

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

Dies gibt True sowohl für Dateien als auch für Verzeichnisse zurück. Sie können stattdessen os.path.isfile , um zu testen, ob es sich um eine Datei handelt. Es folgt Symlinks.

Question

Wie kann man feststellen, ob eine Datei existiert oder nicht, ohne die try Anweisung zu verwenden?




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



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



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



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




import os.path

if os.path.isfile(filepath):



2017/12/22 :

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

Hinweis : Jeder Python- Standardbibliothekscode, den ich posten werde, gehört zur Version 3.5.3 (doc-Anführungszeichen sind spezifisch für Version 3 ).

Problemstellung :

  1. Datei prüfen ( fraglich : auch Ordner ("spezielle" Datei)?) Existenz
  2. Verwenden Sie keine try / except / else / finally Blöcke

Mögliche Lösungen :

  1. [Python]: os.pfad. existiert ( Pfad ) (überprüfen Sie auch andere Mitglieder der Funktionsfamilie wie os.path.isfile , os.path.isdir , os.path.lexists für etwas andere Verhaltensweisen)

    os.path.exists(path)
    

    Gibt True wenn Pfad auf einen vorhandenen Pfad oder einen geöffneten Dateideskriptor verweist. Gibt für fehlerhafte symbolische Links False . Auf einigen Plattformen kann diese Funktion False wenn die Berechtigung zum Ausführen von os.stat() für die angeforderte Datei nicht erteilt wird, selbst wenn der Pfad physisch existiert.

    Alles gut, aber wenn man dem Importbaum folgt:

    • 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 os.stat() os.stat() . Also, dein Code ist try/except free, aber niedriger im framestack gibt es (mindestens) einen solchen Block. Dies gilt auch für andere Funktionen ( einschließlich os.path.isfile ).

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

    • Es ist eine schickere (und mehr python ic) Art, Pfade zu verwalten, aber
    • Unter der Haube macht es genau dasselbe ( 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]: 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 das isfile Verhalten (beachte, dass dies nur zu Demonstrationszwecken ist, versuche 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
        
    • Benutze [Python]: contextlib. suppress ( * exceptions ) - das wurde speziell für die selektive Unterdrückung von Ausnahmen entwickelt


    Aber sie scheinen Wrapper über try/except/else/finally , wie [Python]: Die with- Anweisung besagt:

    Dies ermöglicht den üblichen try ... except ... finally Verwendungsmuster zu kapseln, um sie bequem wiederverwenden zu können.

  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 verwackeltes glob bing - wie @ShadowRanger darauf hingewiesen hat), also werde ich nicht darauf bestehen. Ganz zu schweigen davon, dass in einigen Fällen die Verarbeitung von Dateinamen erforderlich sein kann.

  4. [Python]: os. access ( path, mode, *, dir_fd = None, effective_ids = False, follow_symlinks = True ), dessen Verhalten nah an os.path.exists (eigentlich ist es breiter, hauptsächlich wegen des 2. Arguments)

    • Benutzerberechtigungen können die Sichtbarkeit der Datei einschränken, wie im Dokument angegeben:

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

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

    Da ich auch in C arbeite, benutze ich diese Methode auch, weil sie unter der Haube native APIs aufruft (wiederum via " $ {PYTHON_SRC_DIR} /Modules/posixmodule.c "), aber es öffnet auch ein Tor für mögliche Benutzer Fehler , und es ist nicht wie Python ic als andere Varianten. Also, wie @AaronHall zu Recht darauf hingewiesen hat, benutze es nur, wenn du weißt, was du tust:

    Hinweis : Der Aufruf nativer APIs ist auch über [Python] möglich: ctypes - Eine Fremdfunktions- Bibliothek für Python , aber in den meisten Fällen ist es komplizierter.

    ( Win spezifisch): Da msvcr * ( vcruntime * ) eine [MSDN]: _access, _waccess -Funktionsfamilie ebenfalls exportiert, 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, verwende ich os.F_OK in dem Anruf, aber das dient nur der Übersichtlichkeit (sein Wert ist 0 )
    • Ich verwende _waccess so dass der gleiche Code auf Python3 und Python2 funktioniert (trotz Unicode- bezogener Unterschiede zwischen ihnen)
    • Obwohl dies ein sehr spezifisches Gebiet betrifft, wurde es in keiner der vorherigen Antworten erwähnt


    Das Lnx ( Ubtu (16 x64) ) Pendant 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 :

    • Anstatt den Pfad der libc zu codieren ( "/lib/x86_64-linux-gnu/libc.so.6" ), der sich (und wahrscheinlich auch) von System zu System unterscheidet, kann None (oder die leere Zeichenfolge) an den CDLL Konstruktor übergeben werden ( ctypes.CDLL(None).access(b"/tmp", os.F_OK) ). Laut [Mann]: DLOPEN (3) :

      Wenn Dateiname NULL ist, ist das zurückgegebene Handle für das Hauptprogramm. Wenn dieses Handle dlsym () übergeben wird, bewirkt dieses Handle eine Suche nach einem Symbol im Hauptprogramm, gefolgt von allen beim Programmstart geladenen gemeinsamen Objekten und dann allen gemeinsam genutzten Objekten, die von dlopen () mit dem Flag RTLD_GLOBAL geladen werden .

      • Das (aktuelle) Hauptprogramm ( Python ) ist mit libc verbunden , so dass seine Symbole (einschließlich des access ) geladen werden
      • Dies muss mit Vorsicht behandelt werden, da Funktionen wie main , Py_Main und (alle) anderen verfügbar sind; sie anzurufen, könnte katastrophale Auswirkungen haben (auf das aktuelle Programm)
      • Das gilt nicht auch für Win (aber das ist nicht so eine große Sache, da sich msvcrt.dll in "% SystemRoot% \ System32" befindet, das in % PATH% standardmäßig ist). Ich wollte die Dinge weiterführen und dieses Verhalten auf Win replizieren (und einen Patch senden), aber wie sich herausstellt, "sieht" die Funktion " GetProcAddress " exportierte Symbole nur, wenn jemand die Funktionen in der Hauptprogrammdatei als __declspec(dllexport) (Warum auf der Erde würde die normale Person das tun?), das Hauptprogramm ist ladbar, aber ziemlich unbrauchbar
  5. Installieren Sie ein Drittanbieter- Modul mit Dateisystemfunktionen

    Höchstwahrscheinlich wird sich auf eine der oben genannten Möglichkeiten verlassen (vielleicht mit leichten Anpassungen).
    Ein Beispiel wäre (wiederum Win- spezifisch) [GitHub]: Python für Windows (pywin32) Extensions , das ist ein Python- Wrapper über WINAPI s.

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

  6. 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\\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
      

Fazit :

  • Verwenden Sie try / except / else / finally blocks, da 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



Es scheint nicht, dass es einen sinnvollen funktionalen Unterschied zwischen try / except und isfile() , also solltest du 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.'

Aber wenn Sie nur eine Datei umbenennen möchten, wenn sie existiert, und sie daher nicht öffnen müssen, tun Sie es

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

Wenn Sie in eine Datei schreiben möchten, wenn sie nicht existiert, tun Sie

# 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 Datei sperren müssen, ist das eine andere Sache.




Python 3.4+ hat ein objektorientiertes pathlib : pathlib . Mit diesem neuen Modul können Sie prüfen, ob eine Datei so existiert:

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) immer noch einen try/except Block verwenden, wenn Sie Dateien öffnen:

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

Das Pathlib-Modul enthält viele coole Dinge: praktisches Globbing, Überprüfung des Eigentümers der Datei, einfacherer Pfad-Beitritt usw. Es lohnt sich, es auszuprobieren. Wenn Sie älter sind als Python (Version 2.6 oder höher), können Sie pathlib mit pip installieren:

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

Dann importieren Sie es wie folgt:

# Older Python versions
import pathlib2 as pathlib



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 von Betriebssystemen erleichtert das Navigieren und Ausführen von Standardaktionen mit Ihrem Betriebssystem.

Siehe auch share

Wenn Sie Operationen auf hoher Ebene benötigen, verwenden Sie shutil .




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.




Sie könnten dies (sicherer) versuchen:

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 Verzeichnis: 'whatever.txt')

Dann kann Ihr Programm, abhängig vom Ergebnis, einfach von dort weiterlaufen oder Sie können es mit einem Code stoppen, wenn Sie möchten.




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




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.




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






Links