Jak sprawdzić, czy plik istnieje bez wyjątków?


5601

Jak sprawdzić, czy plik istnieje, czy nie, bez użycia tryinstrukcji?


2
Wydaje się, że jest to klasyczna dyskusja na temat EAFP w porównaniu z LBYL, patrz np. To powiązane pytanie: stackoverflow.com/questions/1835756/using-try-vs-if-in-python
mat 30.10.19

Jest to również istotne, jeśli chcesz wiedzieć, czy jest on obecny na dysku (bezpośrednio lub jako dowiązanie symboliczne), czy możesz z niego czytać lub czy możesz na nim pisać.
Thorbjørn Ravn Andersen

Odpowiedzi:


5152

Jeśli sprawdzasz, że możesz zrobić coś takiego if file_exists: open_it(), bezpieczniej jest skorzystać tryz próby otwarcia. Sprawdzanie, a następnie otwieranie grozi usunięciem lub przeniesieniem pliku lub czymś innym między sprawdzaniem a próbą otwarcia.

Jeśli nie planujesz natychmiast otworzyć pliku, możesz użyć os.path.isfile

Zwróć, Truejeśli ścieżka jest istniejącym zwykłym plikiem. Podąża za dowiązaniami symbolicznymi, więc zarówno islink (), jak i isfile () mogą być prawdziwe dla tej samej ścieżki.

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

jeśli musisz się upewnić, że jest to plik.

Począwszy od Python 3.4, pathlibmoduł oferuje podejście obiektowe (przeniesione do pathlib2Pythona 2.7):

from pathlib import Path

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

Aby sprawdzić katalog, wykonaj:

if my_file.is_dir():
    # directory exists

Aby sprawdzić, czy Pathobiekt istnieje niezależnie od tego, czy jest to plik czy katalog, użyj exists():

if my_file.exists():
    # path exists

Możesz także użyć resolve(strict=True)w trybloku:

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

40
dotyczące pierwszej uwagi (użyj „spróbuj”, jeśli sprawdź przed otwarciem) niestety to nie zadziała, jeśli chcesz otworzyć w celu dołączenia, mając pewność, że już istnieje, ponieważ tryb „a” utworzy, jeśli nie istnieje.
makapuf

6
Zauważ, że FileNotFoundErrorzostał wprowadzony w Pythonie 3. Jeśli potrzebujesz także obsługiwać Python 2.7 oraz Python 3, możesz IOErrorzamiast tego użyć (które FileNotFoundErrorpodklasy) stackoverflow.com/a/21368457/1960959
scottclowe

7
@makapuf Możesz go otworzyć do „aktualizacji” ( open('file', 'r+')), a następnie przejść do końca.
kyrill 30.04.2019

2
@kyrill open-and-seek-to-the-end to nie to samo, co open-for-append (przynajmniej w systemach posix). „tryb dołączania” zawsze poprawnie zapisuje na końcu pliku, nawet jeśli inne rzeczy modyfikują plik między momentem jego otwarcia a momentem zapisu. Otwieranie do zapisu / aktualizacji i szukanie do końca ryzykuje uszkodzenie danych pliku, jeśli wiele rzeczy próbuje zapisać do tego samego pliku w tym samym czasie. Niestety uważam, że jedynym bezpiecznym dla wyścigu sposobem na otwarcie dla dołączenia przy jednoczesnym upewnieniu się, że plik istnieje jako pierwszy, jest użycie procedur os.open () niższego poziomu (O_APPEND bez O_CREAT).
Foogod

1
@LorinczyZsigmond, który brzmi jak zachowanie zależne od implementacji. Chcesz udostępnić źródło?
kyrill

2110

Masz os.path.existsfunkcję:

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

Zwraca Truezarówno pliki, jak i katalogi, ale możesz zamiast tego użyć

os.path.isfile(file_path)

aby sprawdzić, czy jest to konkretnie plik. Podąża za dowiązaniami symbolicznymi.


965

W przeciwieństwie do isfile(), exists()wróci Truepo katalogi. W zależności od tego, czy chcesz tylko zwykłe pliki, czy też katalogi, użyjesz isfile()lub exists(). Oto kilka prostych wyników 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


320

Użyj os.path.isfile()z 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")

60
posiadanie wielu warunków, z których niektóre są zbyteczne, jest mniej jasne i wyraźne.
wim

10
Jest również zbędny. Jeśli plik nie istnieje, os.access()zwróci false.
user207421,

9
@EJP W systemie Linux mogą istnieć pliki, ale nie są dostępne.
e-info128,

8
ponieważ nie import osmusisz tego robić, import os.pathponieważ jest to już część os. Musisz tylko zaimportować, os.pathjeśli zamierzasz używać funkcji z siebie, os.patha nie od ossiebie, aby zaimportować mniejszą rzecz, ale podczas używania os.accessi os.R_OKdrugi import nie jest potrzebny.
Jester

286
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

2
Zasadniczo nie jest dobrą praktyką nazywanie zmiennych tak samo jak nazw metod.
Homunculus Reticulli

245

Chociaż prawie każdy możliwy sposób został wymieniony w (przynajmniej jednej) istniejących odpowiedziach (np. Dodano specyficzne rzeczy w Pythonie 3.4 ), spróbuję pogrupować wszystko razem.

Uwaga : każdy fragment standardowego kodu biblioteki Python, który zamierzam opublikować, należy do wersji 3.5.3 .

Opis problemu :

  1. Sprawdź, czy istnieje plik ( sporny : także folder (plik „specjalny”)?)
  2. Nie używaj bloków try / oprócz / else / wreszcie

Możliwe rozwiązania :

  1. [Python 3]: os.path. istnieje ( ścieżka ) (też sprawdzić innych członków rodziny, takich jak funkcja os.path.isfile, os.path.isdir, os.path.lexistsdla nieco odmiennych zachowań)

    os.path.exists(path)

    Zwraca, Truejeśli ścieżka odnosi się do istniejącej ścieżki lub otwartego deskryptora pliku. Zwraca Falseza zepsute dowiązania symboliczne. Na niektórych platformach funkcja ta może zwrócić, Falsejeśli nie zostanie udzielone uprawnienie do wykonania os.stat () na żądanym pliku, nawet jeśli ścieżka istnieje fizycznie.

    Wszystko dobrze, ale jeśli śledzisz drzewo importu:

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

      • genericpath.py , linia ~ # 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

    to tylko próba / z wyjątkiem bloku wokół [Python 3]: os. stat ( ścieżka, *, dir_fd = Brak, follow_symlinks = True ) . Więc twój kod jest wypróbowany / z wyjątkiem darmowego, ale na dole framestacka jest (przynajmniej) jeden taki blok. Dotyczy to również innych funkcji (w tym os.path.isfile ).

    1.1 [Python 3]: Ścieżka. is_file ()

    • Jest to bardziej wymyślny (i bardziej pythonowy ) sposób obsługi ścieżek, ale
    • Pod maską robi dokładnie to samo ( pathlib.py , linia ~ # 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 3]: Z menedżerami kontekstu instrukcji . Zarówno:

    • Stworzyć jeden:

      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 ...)
      • I jego użycie - powtórzę to os.path.isfilezachowanie (pamiętaj, że jest to tylko w celach demonstracyjnych, nie próbuj pisać takiego kodu do produkcji ):

        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
    • Użyj [Python 3]: contextlib. suppress ( * wyjątki ) - który został specjalnie zaprojektowany do selektywnego tłumienia wyjątków


    Ale wydają się być owijarki ponad próbie / z wyjątkiem / else / wreszcie bloki, jak [Python 3]: z rachunku stanów:

    Pozwala to na powszechną próbę ... z wyjątkiem ... wreszcie , aby wzorce użycia zostały zamknięte w celu wygodnego ponownego użycia.

  3. Funkcje przechodzenia przez system plików (i wyszukaj wyniki dla pasujących elementów)


    Ponieważ powtarzają się one po folderach (w większości przypadków) są nieefektywne w przypadku naszego problemu (są wyjątki, takie jak glob bing bez symboli wieloznacznych - jak wskazał @ShadowRanger), więc nie będę nalegał na nie. Nie wspominając o tym, że w niektórych przypadkach przetwarzanie plików może być wymagane.

  4. [Python 3]: os. access ( ścieżka, tryb, *, dir_fd = Brak, efektywne_ids = Fałsz, follow_symlinks = True ), którego zachowanie jest bliskie os.path.exists(w rzeczywistości jest szersze, głównie z powodu drugiego argumentu)

    • uprawnienia użytkownika mogą ograniczać „widoczność” pliku, jak stwierdza dokument:

      ... sprawdź, czy wywołujący użytkownik ma określony dostęp do ścieżki . tryb powinien być F_OK, aby sprawdzić istnienie ścieżki ...

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

    Ponieważ pracuję także w C , używam tej metody, jak również dlatego, że pod maską, wywołuje natywne API s (znów przez „$ {PYTHON_SRC_DIR} /Modules/posixmodule.c” ), ale także otwiera furtkę dla ewentualnego użytkownika błędy i nie jest tak Python ic jak inne warianty. Tak jak słusznie zauważył @AaronHall, nie używaj go, chyba że wiesz, co robisz:

    Uwaga : wywoływanie natywnego API jest również możliwe przez [Python 3]: ctypes - Biblioteka funkcji obcych dla Pythona , ale w większości przypadków jest bardziej skomplikowana.

    (W szczególności dla Win ): Ponieważ vcruntime * ( msvcr * ) .dll eksportuje [MS.Docs]: _access, a także rodzinę funkcji _waccess , oto przykład:

    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

    Uwagi :

    • Chociaż nie jest to dobra praktyka, używam os.F_OKtego połączenia, ale to tylko dla jasności (jego wartość wynosi 0 )
    • Używam _waccess , aby ten sam kod działał na Python3 i Python2 (pomimo różnic między nimi związanych z Unicode )
    • Chociaż dotyczy to bardzo określonego obszaru, nie wspomniano o nim w żadnej z poprzednich odpowiedzi


    Odpowiednik 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

    Uwagi :

    • Zamiast tego na stałe ścieżka libc ( „/lib/x86_64-linux-gnu/libc.so.6” ), która może (i najprawdopodobniej będzie się różnić) w różnych systemach, Brak (lub pusty ciąg) może zostać przekazany do konstruktora CDLL ( ctypes.CDLL(None).access(b"/tmp", os.F_OK)). Według [man7]: DLOPEN (3) :

      Jeśli nazwa pliku ma wartość NULL, wówczas zwrócony uchwyt dotyczy programu głównego. Po przekazaniu do dlsym () uchwyt ten powoduje wyszukiwanie symbolu w programie głównym, a następnie wszystkie obiekty współdzielone ładowane podczas uruchamiania programu, a następnie wszystkie obiekty współdzielone ładowane przez dlopen () z flagą RTLD_GLOBAL .

      • Główny (bieżący) program ( python ) jest powiązany z libc , więc jego symbole (w tym dostęp ) zostaną załadowane
      • Należy się z tym obchodzić ostrożnie, ponieważ funkcje takie jak main , Py_Main i (wszystkie) inne są dostępne; wywoływanie ich może mieć katastrofalne skutki (w bieżącym programie)
      • Nie dotyczy to również Win (ale to nie jest wielka sprawa, ponieważ msvcrt.dll znajduje się w „% SystemRoot% \ System32”, który domyślnie jest w % PATH% ). Chciałem pójść o krok dalej i zreplikować to zachowanie na Win (i przesłać łatkę), ale jak się okazuje, [MS.Docs]: Funkcja GetProcAddress „widzi” wyeksportowane symbole, więc chyba, że ​​ktoś zadeklaruje funkcje w głównym pliku wykonywalnym ponieważ __declspec(dllexport)(dlaczego na Ziemi zwykła osoba miałaby to robić?), główny program jest wczytywalny, ale praktycznie bezużyteczny
  5. Zainstaluj moduł innej firmy z funkcjami systemu plików

    Najprawdopodobniej będzie polegać na jednym z powyższych sposobów (może z niewielkimi dostosowaniami).
    Jednym z przykładów byłoby (ponownie, specyficzne dla Win ) [GitHub]: mhammond / pywin32 - Rozszerzenia Python dla Windows (pywin32) , które są opakowaniem Pythona w WINAPI .

    Ale ponieważ jest to raczej obejście, zatrzymuję się tutaj.

  6. Innym (kiepskim) obejściem ( gainarie ) jest (jak to nazywam) podejście sysadmin : użyj Pythona jako opakowania do wykonywania poleceń powłoki

    • Wygraj :

      (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

Dolna linia :

  • Czy używanie try / except / else / wreszcie bloków, ponieważ mogą one zapobiec uruchomione na szereg nieprzyjemnych problemów. Kontrapunktem, o którym mogę myśleć, jest wydajność: takie bloki są kosztowne, więc staraj się nie umieszczać ich w kodzie, który powinien działać setki tysięcy razy na sekundę (ale ponieważ (w większości przypadków) wymaga dostępu do dysku, tak nie będzie).

Uwagi końcowe :

  • Postaram się go aktualizować, wszelkie sugestie są mile widziane, uwzględnię wszystko przydatne, które pojawią się w odpowiedzi

3
Czy możesz rozwinąć to oświadczenie? „Chociaż nie jest to dobra praktyka, używam os.F_OK w wywołaniu, ale to tylko dla przejrzystości (jego wartość wynosi 0)”
sk8asd123,

6
@ sk8asd123: Trudno to zrobić w komentarzu: ogólnie najlepiej jest używać stałych z funkcjami, z którymi się łączą. Dotyczy to pracy z wieloma modułami, które definiują tę samą stałą, ponieważ niektóre mogą nie być aktualne i najlepiej jest zsynchronizować funkcje i stałe. Podczas pracy z ctypami (bezpośrednie wywoływanie funkcji) powinienem był zdefiniować stałą (z MSDN ) lub w ogóle nie używać stałej. To tylko wskazówka, której używam, w 99,9% prawdopodobnie nie ma znaczenia (funkcjonalnie).
CristiFati,

3
@CristiFati: Od wersji 3.6 glob.iglob(i glob.globrównież) są oparteos.scandir , więc teraz jest leniwy; aby uzyskać pierwsze trafienie w katalogu 10 mln plików, skanujesz tylko do momentu osiągnięcia pierwszego trafienia. A nawet w wersji wcześniejszej niż 3.6, jeśli używasz globmetod bez symboli wieloznacznych, funkcja jest inteligentna: wie, że możesz mieć tylko jedno trafienie, więc upraszcza globowanie tylko doos.path.isdiros.path.lexists ( lub w zależności od tego, czy ścieżka się kończy /).
ShadowRanger

3
Ta druga część mojego komentarza (globowanie bez symboli wieloznacznych w rzeczywistości nie iteruje folderu i nigdy go nie ma) oznacza, że ​​jest to doskonale wydajne rozwiązanie problemu (wolniejsze niż bezpośrednie wywoływanie os.path.isdirlub os.path.lexistponieważ jest to zbiór wywołań i ciągów funkcji poziomu Pythona operacje, zanim zdecyduje, że efektywna ścieżka jest opłacalna, ale nie wymaga dodatkowego wywołania systemowego ani pracy we / wy, która jest o rząd wielkości wolniejsza).
ShadowRanger

154

Jest to najprostszy sposób sprawdzenia, czy plik istnieje. Tylko dlatego, że plik istniał po sprawdzeniu, nie gwarantuje , że będzie tam, kiedy trzeba go otworzyć.

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

17
Tak długo, jak zamierzasz uzyskać dostęp do pliku, warunki wyścigu istnieją , niezależnie od budowy programu. Twój program nie może zagwarantować, że inny proces na komputerze nie zmodyfikował pliku. Eric Lippert nazywa to egzogenicznym wyjątkiem . Nie można tego uniknąć, sprawdzając wcześniej istnienie pliku.
Isaac Supeene,

@IsaacSupeene Najlepszą praktyką jest, aby okno operacji (pliku) było tak małe, jak to możliwe, a następnie odpowiednia obsługa wyjątków
un33k

145

Python 3.4+ ma obiektowy moduł ścieżki: pathlib . Za pomocą tego nowego modułu możesz sprawdzić, czy plik istnieje w następujący sposób:

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

Możesz (i zwykle powinieneś) nadal używać try/exceptbloku podczas otwierania plików:

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

Moduł pathlib zawiera wiele fajnych rzeczy: wygodne globowanie, sprawdzanie właściciela pliku, łatwiejsze dołączanie ścieżki itp. Warto to sprawdzić. Jeśli korzystasz ze starszego Pythona (wersja 2.6 lub nowsza), nadal możesz zainstalować pathlib za pomocą pip:

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

Następnie zaimportuj go w następujący sposób:

# Older Python versions
import pathlib2 as pathlib

124

Wolę instrukcję try. Jest uważany za lepszy styl i pozwala uniknąć warunków wyścigowych.

Nie wierz mi na słowo. Istnieje mnóstwo poparcia dla tej teorii. Oto kilka:


3
Dodaj lepsze źródła na poparcie swojego oświadczenia.
BlueTrin,

11
Cytowany link Unikanie warunków wyścigu (wsparcie deweloperów Apple) nie obsługuje Twojej odpowiedzi. Dotyczy tylko korzystania z plików tymczasowych zawierających poufne informacje w źle zaprojektowanych systemach operacyjnych, które nie przetwarzają poprawnie plików / katalogów tymczasowych za pomocą ograniczonych uprawnień. Użycie i try...excepttak nie pomaga rozwiązać tego problemu.
jstine

Problem z tą metodą polega na tym, że jeśli masz ważny fragment kodu w zależności od nieistniejącego pliku, umieszczenie go w except:klauzuli sprawi, że wyjątek powstający w tej części kodu wywoła mylący komunikat (drugi błąd zgłoszony podczas przetwarzanie pierwszego.)
Camion

119

Jak sprawdzić, czy plik istnieje, używając Pythona, bez użycia instrukcji try?

Teraz dostępny od Pythona 3.4, importuj i tworzymy instancję Pathobiektu o nazwie pliku, i sprawdź is_filemetodę (zauważ, że to zwraca True dla dowiązań symbolicznych wskazujących również na zwykłe pliki):

>>> from pathlib import Path
>>> Path('/').is_file()
False
>>> Path('/initrd.img').is_file()
True
>>> Path('/doesnotexist').is_file()
False

Jeśli korzystasz z Python 2, możesz backportować moduł pathlib z pypi pathlib2lub w inny sposób sprawdzić isfilez os.pathmodułu:

>>> import os
>>> os.path.isfile('/')
False
>>> os.path.isfile('/initrd.img')
True
>>> os.path.isfile('/doesnotexist')
False

Teraz powyższe jest prawdopodobnie najlepszą pragmatyczną bezpośrednią odpowiedzią tutaj, ale istnieje możliwość wyścigu (w zależności od tego, co próbujesz osiągnąć) oraz fakt, że podstawowa implementacja używa try, ale Python używa trywszędzie w swojej implementacji.

Ponieważ Python używa trywszędzie, naprawdę nie ma powodu, aby unikać implementacji, która go używa.

Ale reszta tej odpowiedzi próbuje rozważyć te zastrzeżenia.

Dłuższa, znacznie bardziej pedantyczna odpowiedź

Dostępne od wersji Python 3.4, użyj nowego Pathobiektu w pathlib. Zauważ, że .existsto nie do końca prawda, ponieważ katalogi nie są plikami (z wyjątkiem tego, że w Uniksie wszystko jest plikiem).

>>> from pathlib import Path
>>> root = Path('/')
>>> root.exists()
True

Musimy więc użyć is_file:

>>> root.is_file()
False

Oto pomoc dotycząca is_file:

is_file(self)
    Whether this path is a regular file (also True for symlinks pointing
    to regular files).

Pobierzmy więc plik, o którym wiemy, że to plik:

>>> import tempfile
>>> file = tempfile.NamedTemporaryFile()
>>> filepathobj = Path(file.name)
>>> filepathobj.is_file()
True
>>> filepathobj.exists()
True

Domyślnie NamedTemporaryFileusuwa plik po zamknięciu (i zostanie automatycznie zamknięty, gdy nie będzie już więcej odwołań do niego).

>>> del file
>>> filepathobj.exists()
False
>>> filepathobj.is_file()
False

Jeśli jednak zagłębisz się w implementację , zobaczysz, że is_fileużywa 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

Warunki wyścigu: Dlaczego lubimy próbować

Lubimy to, tryponieważ pozwala uniknąć warunków wyścigowych. Dzięki trypo prostu próbujesz odczytać plik, oczekując, że on tam będzie, a jeśli nie, wychwytujesz wyjątek i wykonujesz dowolne zachowanie rezerwowe, które ma sens.

Jeśli chcesz sprawdzić, czy plik istnieje, zanim spróbujesz go odczytać, być może usuwasz go, a następnie korzystasz z wielu wątków lub procesów lub inny program wie o tym pliku i może go usunąć - ryzykujesz wyścigu sprawdzając istnieje, bo są wtedy wyścigi , aby otworzyć go przed jego stanu (jego istnienie) zmienia.

Warunki wyścigu są bardzo trudne do debugowania, ponieważ istnieje bardzo małe okno, w którym mogą spowodować awarię programu.

Ale jeśli to jest twoja motywacja, to można uzyskać wartość tryrachunku za pomocą suppressmenedżera kontekstowe.

Unikanie warunków wyścigu bez instrukcji try: suppress

Python 3.4 udostępnia nam suppressmenedżera kontekstu (wcześniej ignoremenedżera kontekstu), który robi semantycznie dokładnie to samo w mniejszej liczbie wierszy, a jednocześnie (przynajmniej powierzchownie) spełnia oryginalne zapytanie o uniknięcie tryinstrukcji:

from contextlib import suppress
from pathlib import Path

Stosowanie:

>>> with suppress(OSError), Path('doesnotexist').open() as f:
...     for line in f:
...         print(line)
... 
>>>
>>> with suppress(OSError):
...     Path('doesnotexist').unlink()
... 
>>> 

W przypadku wcześniejszych Pytonów możesz rzucić własne suppress, ale bez nich trybędzie bardziej gadatliwy niż z. Wierzę, że tak naprawdę jest to jedyna odpowiedź, która nie jest używana tryna żadnym poziomie w Pythonie, którą można zastosować przed Pythonem 3.4, ponieważ zamiast tego używa menedżera kontekstu:

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)

Być może łatwiejsze z próbą:

from contextlib import contextmanager

@contextmanager
def suppress(*exceptions):
    try:
        yield
    except exceptions:
        pass

Inne opcje, które nie spełniają warunku „bez próby”:

plik is

import os
os.path.isfile(path)

z dokumentów :

os.path.isfile(path)

Zwraca wartość True, jeśli ścieżka jest istniejącym zwykłym plikiem. Wynika to dowiązania symboliczne, tak jak islink()i isfile()może być prawdziwe w odniesieniu do tej samej ścieżce.

Ale jeśli zbadasz źródło tej funkcji, zobaczysz, że faktycznie używa instrukcji 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

Wystarczy, że użyje podanej ścieżki, aby sprawdzić, czy może uzyskać statystyki, przechwytuje, OSErrora następnie sprawdza, czy jest to plik, jeśli nie zgłosił wyjątku.

Jeśli zamierzasz coś zrobić z plikiem, sugerowałbym bezpośrednią próbę spróbowania, z wyjątkiem uniknięcia wyścigu:

try:
    with open(path) as f:
        f.read()
except OSError:
    pass

os.access

Dostępny jest dla systemów Unix i Windows os.access, ale aby go użyć, musisz przekazać flagi i nie rozróżnia on plików i katalogów. Jest to bardziej wykorzystywane do testowania, czy rzeczywisty wywołujący użytkownik ma dostęp w środowisku o podwyższonych uprawnieniach:

import os
os.access(path, os.F_OK)

Ma także takie same problemy z wyścigiem jak isfile. Z dokumentów :

Uwaga: Użycie access () do sprawdzenia, czy użytkownik jest upoważniony np. Do otwarcia pliku, zanim faktycznie to zrobi, użycie open () tworzy lukę w zabezpieczeniach, ponieważ użytkownik może wykorzystać krótki odstęp czasu między sprawdzeniem a otwarciem pliku, aby nim manipulować. Lepiej jest stosować techniki EAFP. Na przykład:

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

lepiej napisać jako:

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

Unikaj używania os.access. Jest to funkcja niskiego poziomu, która ma więcej możliwości wystąpienia błędu użytkownika niż obiekty i funkcje wyższego poziomu omówione powyżej.

Krytyka innej odpowiedzi:

Inna odpowiedź mówi o tym os.access:

Osobiście wolę ten, ponieważ pod maską wywołuje natywne interfejsy API (przez „$ {PYTHON_SRC_DIR} /Modules/posixmodule.c”), ale otwiera także bramę dla możliwych błędów użytkownika i nie jest tak Pythonic jak inne warianty :

Ta odpowiedź mówi, że woli bez skłonności do Pythona, podatna na błędy, bez uzasadnienia. Wygląda na to, że zachęca użytkowników do korzystania z niskopoziomowych interfejsów API bez ich zrozumienia.

Tworzy również menedżera kontekstu, który poprzez bezwarunkowe zwracanie Truepozwala wszystkim wyjątkom (w tym KeyboardInterrupti SystemExit!) Przejść cicho, co jest dobrym sposobem na ukrycie błędów.

Wydaje się, że zachęca to użytkowników do stosowania złych praktyk.


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

Importowanie osułatwia nawigację i wykonywanie standardowych działań w systemie operacyjnym.

W celach informacyjnych zobacz także Jak sprawdzić, czy plik istnieje za pomocą Pythona?

Jeśli potrzebujesz operacji na wysokim poziomie, użyj shutil.


9
Ta odpowiedź jest zła. os.path.existszwraca true dla rzeczy, które nie są plikami, takich jak katalogi. To daje wyniki fałszywie pozytywne. Zobacz inne odpowiedzi, które zalecają os.path.isfile.
Chris Johnson

84

Testowanie plików i folderów z os.path.isfile(), os.path.isdir()ios.path.exists()

Zakładając, że „ścieżka” jest prawidłową ścieżką, ta tabela pokazuje, co każda funkcja zwraca do plików i folderów:

wprowadź opis zdjęcia tutaj

Możesz również przetestować, czy plik jest określonego typu, używając go os.path.splitext()do uzyskania rozszerzenia (jeśli jeszcze go nie znasz)

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

72

W 2016 roku najlepszym sposobem jest nadal os.path.isfile:

>>> os.path.isfile('/path/to/some/file.txt')

Lub w Python 3 możesz użyć pathlib:

import pathlib
path = pathlib.Path('/path/to/some/file.txt')
if path.is_file():
    ...

3
Czy mogę zapytać: jaka jest zaleta korzystania z modułu „pathlib” zamiast modułu „os” w python3 do tego sprawdzania?
Joko,

3
pathlibjest rozwiązaniem OOP dla ścieżek w Pythonie. Dzięki temu możesz zrobić znacznie więcej. Jeśli potrzebujesz tylko sprawdzić istnienie, przewaga nie jest tak duża.
KaiBuxe,

65

Nie wydaje się, aby istniała znacząca funkcjonalna różnica między try / wyjątkiem a isfile(), więc powinieneś użyć tego, który ma sens.

Jeśli chcesz odczytać plik, jeśli istnieje, zrób to

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

Ale jeśli chcesz tylko zmienić nazwę pliku, jeśli istnieje, i dlatego nie musisz go otwierać, zrób to

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

Jeśli chcesz zapisać do pliku, jeśli nie istnieje, zrób to

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

Jeśli potrzebujesz blokowania plików, to inna sprawa.


3
Ta odpowiedź jest zła. os.path.existszwraca true dla rzeczy, które nie są plikami, takich jak katalogi. To daje wyniki fałszywie pozytywne. Zobacz inne odpowiedzi, które zalecają os.path.isfile.
Chris Johnson

6
W trzecim przykładzie tworzę link o filepathodpowiednim czasie, a BAM zastępujesz plik docelowy. Powinieneś zrobić open(filepath, 'wx')w try...exceptbloku, aby uniknąć problemu.
spectras

1
W drugim przykładzie, przynajmniej w systemie Windows, otrzymasz komunikat „ OSErrorjeśli filepath + '.old'już istnieje”: „W systemie Windows, jeśli dst już istnieje, OSError zostanie podniesiony, nawet jeśli jest to plik; może nie być możliwości zaimplementowania atomowej zmiany nazwy, gdy dst nazywa istniejący plik. ”
Tom Myddeltyn

@TomMyddeltyn: Począwszy od Python 3.3,os.replace przenośnie wykonuje cichą zamianę pliku docelowego (jest identyczny z os.renamezachowaniem Linuxa) (błąd tylko wtedy, gdy istnieje nazwa docelowa i jest katalogiem). Więc utknąłeś na wersji 2.x, ale użytkownicy Py3 mają dobrą opcję od kilku lat.
ShadowRanger

Na renameprzykładzie: należy to zrobić za pomocą try/ except. os.rename(lub os.replacena współczesnym Pythonie) jest atomowy; sprawdzanie, a następnie zmiana nazwy wprowadza niepotrzebny wyścig i dodatkowe wywołania systemowe. Po prostu zróbtry: os.replace(filepath, filepath + '.old') except OSError: pass
ShadowRanger

59

Możesz spróbować (bezpieczniej):

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

Wyjście byłoby:

([Errno 2] Brak takiego pliku lub katalogu: „okolwiek.txt ”)

Następnie, w zależności od wyniku, twój program może po prostu dalej działać od tego miejsca lub możesz napisać kod, aby go zatrzymać, jeśli chcesz.


18
Oryginalny pytanie poprosił o rozwiązanie, które nie używajątry
RR

5
Ta odpowiedź nie zgadza się z celem PO. Sprawdzanie, czy plik istnieje, nie jest tym samym, co sprawdzanie, czy można go otworzyć. Zdarzają się przypadki, w których plik istnieje, ale z różnych powodów nie można go otworzyć.
Chris Johnson

51

Chociaż zawsze polecam używanie tryi exceptoświadczenia, oto kilka możliwości dla ciebie (mój osobisty faworyt używa os.access):

  1. Spróbuj otworzyć plik:

    Otwarcie pliku zawsze weryfikuje jego istnienie. Możesz zrobić taką funkcję:

    def File_Existence(filepath):
        f = open(filepath)
        return True

    Jeśli ma wartość False, przestanie działać z nieobsługiwanym IOError lub OSError w późniejszych wersjach Pythona. Aby złapać wyjątek, musisz użyć klauzuli try oprócz. Oczywiście zawsze możesz użyć tryinstrukcji wyjątku w ten sposób (dzięki hsandt za zmuszenie mnie do myślenia):

    def File_Existence(filepath):
        try:
            f = open(filepath)
        except IOError, OSError: # Note OSError is for later versions of Python
            return False
    
        return True
  2. Użyj os.path.exists(path):

    Spowoduje to sprawdzenie istnienia tego, co określisz. Sprawdza jednak pliki i katalogi, więc uważaj na to, jak z nich korzystasz.

    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
  3. Użyj os.access(path, mode):

    Spowoduje to sprawdzenie, czy masz dostęp do pliku. Sprawdzi uprawnienia. W oparciu o dokumentację os.py, wpisując os.F_OK, sprawdzi istnienie ścieżki. Jednak użycie tego spowoduje powstanie luki w zabezpieczeniach, ponieważ ktoś może zaatakować twój plik, wykorzystując czas między sprawdzeniem uprawnień a otwarciem pliku. Zamiast tego powinieneś przejść bezpośrednio do otwierania pliku zamiast sprawdzania jego uprawnień. ( EAFP vs LBYP ). Jeśli nie zamierzasz później otwierać pliku i sprawdzasz tylko jego istnienie, możesz tego użyć.

    W każdym razie tutaj:

    >>> import os
    >>> os.access("/is/a/file.txt", os.F_OK)
    True

Powinienem także wspomnieć, że istnieją dwa sposoby, aby nie można było zweryfikować istnienia pliku. Albo będzie to problem, permission deniedalbo no such file or directory. Jeśli złapiesz IOError, ustaw IOError as e(jak moja pierwsza opcja), a następnie wpisz, print(e.args)aby, miejmy nadzieję, ustalić problem. Mam nadzieję, że to pomoże! :)


51

Data: 04.12.2017

Każde możliwe rozwiązanie zostało wymienione w innych odpowiedziach.

Intuicyjny i dyskusyjny sposób sprawdzenia, czy plik istnieje, jest następujący:

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

Zrobiłem wyczerpującą ściągę dla twojego odniesienia:

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

37

Jeśli plik jest przeznaczony do otwarcia, możesz użyć jednej z następujących technik:

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

AKTUALIZACJA

Aby uniknąć nieporozumień i na podstawie otrzymanych odpowiedzi, bieżąca odpowiedź znajduje plik lub katalog o podanej nazwie.


9
Ta odpowiedź jest zła. os.path.existszwraca true dla rzeczy, które nie są plikami, takich jak katalogi. To daje wyniki fałszywie pozytywne. Zobacz inne odpowiedzi, które zalecają os.path.isfile.
Chris Johnson

dostał również fałszywie pozytywny problem.
Zorglub29,

docs.python.org/3/library/os.path.html#os.path.exists Do powyższego oświadczenia z chris >> os.path.exists (ścieżka)> Zwróć wartość True, jeśli ścieżka odnosi się do istniejącej ścieżki lub otwartej deskryptor pliku. Zwraca wartość Fałsz za zepsute dowiązania symboliczne. Na niektórych platformach funkcja ta może zwrócić False, jeśli nie zostanie udzielone uprawnienie do wykonania os.stat () na żądanym pliku, nawet jeśli ścieżka istnieje fizycznie. Zmieniono w wersji 3.3: ścieżka może być teraz liczbą całkowitą: Prawda jest zwracana, jeśli jest otwartym deskryptorem pliku, w przeciwnym razie Fałsz. Zmieniono w wersji 3.6: Akceptuje obiekt podobny do ścieżki.
JayRizzo

36

Dodatkowo os.access():

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

Będąc R_OK, W_OKi X_OKflagi do testowania uprawnień ( doc ).


20
if os.path.isfile(path_to_file):
    try: 
        open(path_to_file)
            pass
    except IOError as e:
        print "Unable to open file"

Zgłaszanie wyjątków jest uważane za akceptowalne i Pythoniczne podejście do kontroli przepływu w twoim programie. Rozważ obsługę brakujących plików za pomocą IOErrors. W tej sytuacji wyjątek IOError zostanie zgłoszony, jeśli plik istnieje, ale użytkownik nie ma uprawnień do odczytu.

SRC: http://www.pfinn.net/python-check-if-file-exists.html


3
OP zapytał, jak sprawdzić, czy plik istnieje. Plik może istnieć, ale nie możesz go otworzyć. Dlatego użycie otwarcia pliku jako proxy do sprawdzenia, czy plik istnieje, jest nieprawidłowe: będzie zawierało fałszywe negatywy.
Chris Johnson

19

Jeśli importowane NumPy już do innych celów, to nie ma potrzeby, aby importować innych bibliotek, takich jak pathlib, os, paths, itd.

import numpy as np
np.DataSource().exists("path/to/your/file")

Zwróci wartość prawda lub fałsz na podstawie jego istnienia.


18

Możesz napisać sugestię Briana bez try:.

from contextlib import suppress

with suppress(IOError), open('filename'):
    process()

suppressjest częścią Python 3.4. W starszych wersjach możesz szybko napisać własne pomijanie:

from contextlib import contextmanager

@contextmanager
def suppress(*exceptions):
    try:
        yield
    except exceptions:
        pass

17

Jestem autorem pakietu, który istnieje około 10 lat i ma funkcję, która bezpośrednio rozwiązuje to pytanie. Zasadniczo, jeśli korzystasz z systemu innego niż Windows, używa Popendostępu find. Jeśli jednak korzystasz z systemu Windows, replikuje się findza pomocą wydajnego systemu plików.

Sam kod nie używa trybloku… z wyjątkiem określania systemu operacyjnego i kierowania do stylu „Unix” findlub ręcznego buillta find. Testy czasowe wykazały, że tryszybsze było określanie systemu operacyjnego, więc użyłem jednego z nich (ale nigdzie indziej).

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

A dokument…

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

>>>

Wdrożenie, jeśli chcesz wyglądać, jest tutaj: https://github.com/uqfoundation/pox/blob/89f90fb308f285ca7a62eabe2c38acb87e89dad9/pox/shutils.py#L190


17

Sprawdź plik lub katalog istnieje

Możesz postępować zgodnie z tymi trzema sposobami:

Uwaga 1: os.path.isfileUżywane tylko dla plików

import os.path
os.path.isfile(filename) # True if file exists
os.path.isfile(dirname) # False if directory exists

Uwaga 2: os.path.existsUżywany zarówno dla plików, jak i katalogów

import os.path
os.path.exists(filename) # True if file exists
os.path.exists(dirname) #True if directory exists

pathlib.PathSposób (w Pythonie 3+ instalowane z pip Pythona 2)

from pathlib import Path
Path(filename).exists()

16

Dodanie jeszcze jednej niewielkiej zmiany, która nie jest dokładnie odzwierciedlona w innych odpowiedziach.

Zajmie się to przypadkiem file_pathistnienia Nonelub pustym ciągiem.

def file_exists(file_path):
    if not file_path:
        return False
    elif not os.path.isfile(file_path):
        return False
    else:
        return True

Dodanie wariantu na podstawie sugestii Shahbaz

def file_exists(file_path):
    if not file_path:
        return False
    else:
        return os.path.isfile(file_path)

Dodanie wariantu na podstawie sugestii Petera Wooda

def file_exists(file_path):
    return file_path and os.path.isfile(file_path):

3
if (x) return true; else return false;jest naprawdę sprawiedliwy return x. Twoje cztery ostatnie linie mogą się stać return os.path.isfile(file_path). Skoro już o tym mowa, całą funkcję można uprościć jako return file_path and os.path.isfile(file_path).
Shahbaz

Musisz zachować ostrożność return xw przypadku if (x). Python rozważy pusty ciąg Fałsz, w którym to przypadku zwracalibyśmy pusty ciąg zamiast bool. Celem tej funkcji jest zawsze zwracanie wartości bool.
Marcel Wilson,

1
Prawdziwe. W tym przypadku jednak xjest os.path.isfile(..)tak, że już bool.
Shahbaz

os.path.isfile(None)podnosi wyjątek, dlatego dodałem czek if. Prawdopodobnie mógłbym to po prostu zawinąć w try / oprócz, ale czułem, że w ten sposób było to bardziej wyraźne.
Marcel Wilson,

3
return file_path and os.path.isfile(file_path)
Peter Wood,

15

Oto jedno wierszowe polecenie Python dla środowiska wiersza poleceń Linux. Uważam to za BARDZO HANDY, ponieważ nie jestem tak gorącym facetem Bash.

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

Mam nadzieję, że to jest pomocne.


6
Sprawdzanie jednowierszowe w bash: [ -f "${file}" ] && echo "file found" || echo "file not found"(to samo co if [ ... ]; then ...; else ...; fi).
flotzilla,

12

Możesz użyć biblioteki „OS” Pythona:

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

5
Ta odpowiedź jest zła. os.path.existszwraca true dla rzeczy, które nie są plikami, takich jak katalogi. To daje wyniki fałszywie pozytywne. Zobacz inne odpowiedzi, które zalecają os.path.isfile.
Chris Johnson

@Chris Johnson, funkcja os.path.exists () sprawdza, czy ścieżka istnieje w systemie. ŚCIEŻKA może być DIRECTORY lub FILE. Będzie działać dobrze w obu przypadkach. Spróbuj z jakimś przykładem
Pradip Das

Ta odpowiedź działa. Świetny. Iff ścieżka nie jest ścieżką do pliku. Czy o to chodziło w pytaniu? Nie.
Debosmit Ray

To zależy. Jeśli celem ustalenia istnienia „pliku” jest ustalenie, czy ścieżka już istnieje (i dlatego nie jest ścieżką, w której można przechowywać nowe dane bez usuwania innych informacji), to existsjest w porządku. Jeśli celem jest ustalenie, czy bezpiecznie można otworzyć prawdopodobnie istniejący plik, wówczas krytyka jest uzasadniona i nie jest wystarczająco precyzyjna. Niestety OP nie określa, który cel jest pożądany (i prawdopodobnie już tego nie zrobi).
starturtle

12

Jak sprawdzić, czy plik istnieje, bez użycia instrukcji try?

W 2016 r. Jest to prawdopodobnie najłatwiejszy sposób sprawdzenia, czy plik istnieje i czy jest to plik:

import os
os.path.isfile('./file.txt')    # Returns True if exists, else False

isfilejest właściwie tylko metodą pomocniczą, która jest wewnętrznie używana os.stati stat.S_ISREG(mode)znajduje się pod spodem. Jest os.statto metoda niższego poziomu, która zapewni szczegółowe informacje o plikach, katalogach, gniazdach, buforach i innych. Więcej o os.stat tutaj

Uwaga: jednak to podejście nie blokuje pliku w żaden sposób, dlatego kod może stać się podatny na błędy związane z „ czasem sprawdzenia do czasu użycia ” ( TOCTTOU ).

Dlatego zgłaszanie wyjątków jest uważane za akceptowalne i Pythoniczne podejście do kontroli przepływu w twoim programie. I należy rozważyć obsługę brakujących plików za pomocą IOErrors, a nie ifinstrukcji ( tylko rada ).


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

@ j6m8 tak, isReadableFile(path,fileName)zwróci, Truejeśli plik jest osiągalny i możliwy do odczytu przez proces \ program \ wątek
Khaled.K
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.