Jak sprawdzić, czy plik istnieje, czy nie, bez używania try
komunikat?
Jak sprawdzić, czy plik istnieje, czy nie, bez używania try
komunikat?
Jeśli powodem, dla którego sprawdzasz, możesz zrobić coś takiego if file_exists: open_it()
, bezpieczniej jest używać a try
wokół próby otwarcia. Sprawdzanie i otwieranie ryzykuje usunięcie lub przeniesienie pliku lub coś pomiędzy sprawdzaniem i próbą otwarcia.
Jeśli nie chcesz od razu otwierać pliku, możesz użyć os.path.isfile
Powrót
True
jeśli ścieżka jest istniejącym zwykłym plikiem. Podąża za symbolicznymi linkami, więc oba islink () i isfile () może być prawdziwe dla tej samej ścieżki.
import os.path
os.path.isfile(fname)
jeśli musisz mieć pewność, że to plik.
Począwszy od wersji 3.4 Python pathlib
moduł oferuje podejście obiektowe (przeniesione do pathlib2
w Pythonie 2.7):
from pathlib import Path
my_file = Path("/path/to/file")
if my_file.is_file():
# file exists
Aby sprawdzić katalog, wykonaj następujące czynności:
if my_file.is_dir():
# directory exists
Aby sprawdzić, czy Path
obiekt 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()
w try
blok:
try:
my_abs_path = my_file.resolve()
except FileNotFoundError:
# doesn't exist
else:
# exists
Masz os.path.exists
funkcjonować:
import os.path
os.path.exists(file_path)
To się zwraca True
zarówno dla plików, jak i katalogów, ale możesz zamiast tego użyć
os.path.isfile(file_name)
przetestować, czy jest to plik specjalnie. Podąża za dowiązaniami symbolicznymi.
w odróżnieniu isfile()
, exists()
wróci True
dla katalogów.
Więc w zależności od tego, czy chcesz używać tylko zwykłych plików, czy też katalogów, użyjesz isfile()
lub exists()
. Oto proste wyjście REPL.
>>> 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
import os.path
if os.path.isfile(filepath):
Posługiwać się os.path.isfile()
z 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"
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
Jest to najprostszy sposób sprawdzenia, czy plik istnieje. Właśnie bo plik istnieje, gdy zaznaczyłeś, nie gwarancja że będzie tam, kiedy będziesz musiał 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")
2017/12/22:
Chociaż prawie każdy możliwy sposób został wymieniony w (przynajmniej jednej z) istniejących odpowiedzi (np. Python 3.4 określone rzeczy zostały dodane), spróbuję pogrupować wszystko razem.
Uwaga: każdy kawałek Pyton standardowy kod biblioteki, który mam zamiar opublikować, należy do wersji 3.5.3 (Cytaty doc są wersją 3 konkretny).
Stwierdzenie problemu:
try
/ except
/ else
/ finally
BlokiMożliwe rozwiązania:
[Python]: os.path.istnieje(ścieżka) (sprawdź także inne funkcje członków rodziny, takie jak os.path.isfile
, os.path.isdir
, os.path.lexists
dla nieco innych zachowań)
os.path.exists(path)
Powrót
True
gdyby ścieżka odnosi się do istniejącej ścieżki lub otwartego deskryptora pliku. ZwrotyFalse
dla zepsutych dowiązań symbolicznych. Na niektórych platformach ta funkcja może powrócićFalse
jeśli uprawnienie nie zostanie udzielone do wykonania os.stat () na żądanym pliku, nawet jeśli ścieżka fizycznie istnieje.
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 try/except
blokuj wokół [Python]: os.stat(ścieżka, *, dir_fd = Brak, follow_symlinks = True). Twój kod jest try/except
wolny, ale niższy w framestack (przynajmniej) jeden taki blok. Dotyczy to również innych funkcji (włącznie z os.path.isfile
).
1.1. [Python]: pathlib.Path.is_file()
Pod maską to 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
[Python]: With Statement Context Managers. 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 - będę replikować isfile
zachowanie (zauważ, że jest to tylko do celów demonstracyjnych, nie nie spróbuj napisać taki kod dla produkcja):
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
Posługiwać się [Python]: contextlib.stłumić(* wyjątki) - który był konkretnie Przeznaczony do selektywnego tłumienia wyjątków
Ale wydają się być owijkami try/except/else/finally
bloki, jako [Python]: The z komunikat stwierdza:
To pozwala na wspólne próbować...z wyjątkiem...Wreszcie wzorce użycia do hermetyzacji dla wygodnego ponownego użycia.
Funkcje przejścia systemu plików (i wyszukiwanie wyników dla pasujących elementów)
[Python]: os.listdir(ścieżka = ".") (lub [Python]: os.skandir(ścieżka = ".") na Python v3.5+)
Za pomocą scandir () zamiast listdir () może znacznie zwiększyć wydajność kodu, który również potrzebuje informacji o typie pliku lub atrybucie pliku, ponieważ os.DirEntry obiekty udostępniają te informacje, jeśli system operacyjny udostępnia je podczas skanowania katalogu. Wszystko os.DirEntry metody mogą wykonywać wywołania systemowe, ale is_dir () i is_file () zwykle wymagają tylko wywołania systemowego dla dowiązań symbolicznych; os.DirEntry.stat () zawsze wymaga wywołania systemowego w systemie Unix, ale wymaga tylko jednego dla dowiązań symbolicznych w systemie Windows.
os.listdir
(os.scandir
kiedy dostępny)os.listdir
Ponieważ te iteracje nad folderami (w większości przypadków) są nieskuteczne dla naszego problemu (są wyjątki, na przykład niezgałęzione globbing - jak zauważył @ShadowRanger), więc nie zamierzam ich nalegać. Nie wspominając o tym, że w niektórych przypadkach może być wymagane przetwarzanie pliku.
[Python]: os.dostęp(ścieżka, tryb, *, dir_fd = Brak, effective_ids = False, follow_symlinks = True) którego zachowanie jest bliskie os.path.exists
(w rzeczywistości jest szerszy, głównie z powodu 2nd argument)
... sprawdź, czy użytkownik wywołujący ma określony dostęp ścieżka. tryb powinno być F_OK przetestować istnienie ścieżki ...
os.access("/tmp", os.F_OK)
Od kiedy również pracuję doUżywam tej metody również dlatego, że pod maską dzwoni ojczysty APIs (ponownie, przez "$ {PYTHON_SRC_DIR} /Modules/posixmodule.c"), ale otwiera również bramę dla możliwości błędy użytkownikai to nie jest tak Pytonic jak inne warianty. Tak więc, jak słusznie zauważyła @AaronHall, nie używaj go, chyba że wiesz, co robisz:
Uwaga: dzwonienie natywnie APIs jest również możliwe przez [Pyton]: ctypes - Obca biblioteka funkcji dla Pythona, ale w większości przypadków jest to bardziej skomplikowane.
(Zdobyć specyficzne): od msvcr *(vcruntime *) eksportuje a [MSDN]: _access, _waccess również rodzina funkcji, 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", os.F_OK) -1
Uwagi:
os.F_OK
w rozmowie, ale to tylko dla jasności (jego wartość jest 0)_waccess
aby ten sam kod działał Python3 i Python2 (pomimo unicode powiązane różnice między nimi)
The Lnx (Ubtu (16 x64)) również odpowiednik:
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
Uwagi:
Zamiast twardego kodowania libcścieżka ("/lib/x86_64-linux-gnu/libc.so.6"), które mogą (i najprawdopodobniej będą) różnić się w różnych systemach, None
(lub pusty ciąg) można przekazać do CDLL
konstruktor (ctypes.CDLL(None).access(b"/tmp", os.F_OK)
). Według [mężczyzna]: DLOPEN (3):
Gdyby Nazwa pliku ma wartość NULL, a następnie zwrócona klamka jest dla głównej program. Po podaniu dlsym(), ten uchwyt powoduje wyszukiwanie a symbol w głównym programie, a następnie wszystkie udostępnione obiekty załadowane w uruchomienie programu, a następnie wszystkie udostępnione obiekty załadowane przez dlopen() z Flaga RTLD_GLOBAL.
access
) zostanie załadowanymain
, Py_Main
i (wszystkie) inne są dostępne; ich wywoływanie może mieć katastrofalne skutki (w obecnym programie)__declspec(dllexport)
(dlaczego na Ziemi regularny człowiek to zrobił?), program główny jest ładowalny, ale prawie bezużytecznyZainstaluj około 3r & D Moduł Party z możliwościami systemu plików
Najprawdopodobniej będzie polegać na jednym ze sposobów powyżej (może z niewielkimi dostosowaniami).
Jednym z przykładów byłaby (ponownie Zdobyć konkretny) [GitHub]: Rozszerzenia Python dla Windows (pywin32), który jest Pyton otoki się WINAPIs.
Ale ponieważ jest to bardziej podobne do obejścia, zatrzymuję się tutaj.
Kolejne (lame) obejście (gainarie) jest (jak lubię to nazywać) sysadmin podejście: użycie Pyton jako wrapper do wykonywania poleceń powłoki
Zdobyć:
(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
Dolna linia:
try
/ except
/ else
/ finally
bloków, ponieważ mogą one zapobiec pojawieniu się serii nieprzyjemnych problemów. Kontrapunktem, który mogę wymyślić, 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).Ostateczna uwaga (e):
Python 3.4+ ma obiektowy moduł ścieżki: pathlib. Korzystając z 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 zazwyczaj powinno) nadal używać a try/except
blokuj 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 łączenie ścieżek itp. Warto to sprawdzić. Jeśli używasz 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