Hoe controleer ik of een bestand bestaat of niet, zonder de try
verklaring?
Antwoord 1, autoriteit 100%
Als de reden dat u controleert, is dat u iets kunt doen als if file_exists: open_it()
, is het veiliger om een try
te gebruiken rond de poging om het te openen . Als u controleert en vervolgens opent, loopt u het risico dat het bestand wordt verwijderd of verplaatst of iets tussen wanneer u controleert en wanneer u het probeert te openen.
Als u niet van plan bent het bestand onmiddellijk te openen, kunt u os.path.isfile
Retourneer
True
als pad een bestaand regulier bestand is. Dit volgt op symbolische links, dus zowel islink() als isfile() kan waar zijn voor hetzelfde pad.
import os.path
os.path.isfile(fname)
als je zeker wilt weten dat het een bestand is.
Vanaf Python 3.4, de pathlib
module biedt een objectgeoriënteerde benadering (terug naar pathlib2
in Python 2.7):
from pathlib import Path
my_file = Path("/path/to/file")
if my_file.is_file():
# file exists
Als u een directory wilt controleren, doet u het volgende:
if my_file.is_dir():
# directory exists
Om te controleren of een Path
-object bestaat, ongeacht of het een bestand of map is, gebruikt u exists()
:
if my_file.exists():
# path exists
Je kunt ook resolve(strict=True)
gebruiken in een try
-blok:
try:
my_abs_path = my_file.resolve(strict=True)
except FileNotFoundError:
# doesn't exist
else:
# exists
Antwoord 2, autoriteit 41%
Je hebt de os.path.exists
functie:
import os.path
os.path.exists(file_path)
Dit retourneert True
voor zowel bestanden als mappen, maar u kunt in plaats daarvan gebruik maken van
os.path.isfile(file_path)
om te testen of het specifiek een bestand is. Het volgt symbolische links.
Antwoord 3, autoriteit 19%
In tegenstelling tot isfile()
, exists()
retourneert True
voor mappen. Dus afhankelijk van of je alleen gewone bestanden of ook mappen wilt, gebruik je isfile()
of exists()
. Hier is wat eenvoudige REPL-uitvoer:
>>> 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
Antwoord 4, autoriteit 13%
import os.path
if os.path.isfile(filepath):
print("File exists")
Antwoord 5, autoriteit 7%
Gebruik os.path.isfile()
met 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")
Antwoord 6, autoriteit 6%
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
Antwoord 7, autoriteit 5%
Hoewel bijna elke mogelijke manier is vermeld in (minstens één van) de bestaande antwoorden (bijv. Python 3.4 specifieke dingen zijn toegevoegd), zal ik proberen alles te groeperen.
Opmerking: elk stukje Python standaard bibliotheekcode dat ik ga posten, behoort tot versie 3.5.3.
Probleemstelling:
- Controleer bestand (betwistbaar: ook map (“speciaal” bestand)?) bestaan
- Niet gebruiken probeer / behalve / anders / eindelijk blokken
Mogelijke oplossingen:
-
[Python 3]: os. path.bestaat(path) (controleer ook andere functiefamilieleden zoals
os.path.isfile
,os.path.isdir
,os.path.lexists
voor iets ander gedrag)os.path.exists(path)
Retourneer
True
als pad verwijst naar een bestaand pad of een open bestandsdescriptor. RetourneertFalse
voor verbroken symbolische links. Op sommige platforms kan deze functieFalse
retourneren als er geen toestemming is verleend om os.stat() op het gevraagde bestand, zelfs als het pad fysiek bestaat.Alles goed, maar als je de importboom volgt:
-
os.path
– posixpath.py (ntpath.py)-
genericpath.py, regel ~#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
-
het is gewoon een probeer / behalve blokkade rond [Python 3]: os.stat(pad, *, dir_fd=Geen, follow_symlinks =Waar). Je code is dus probeer / behalve gratis, maar lager in de framestack is er (minstens) een zo’n blok. Dit geldt ook voor andere functies (inclusief
os.path.isfile
).1.1. [Python 3]: Pad.is_file ()
- Het is een mooiere (en meer pythonic) manier om met paden om te gaan, maar
-
Onder de motorkap doet het exact hetzelfde (pathlib.py, regel ~#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]: Met Statement Context Managers. Ofwel:
-
Maak er een:
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 ...)
-
En het gebruik ervan – ik repliceer het
os.path.isfile
-gedrag (merk op dat dit alleen voor demonstratiedoeleinden is, probeer niet te schrijven dergelijke code voor productie):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
-
-
Gebruik [Python 3]: contextlib. onderdrukken(*uitzonderingen) – die specifiek is ontworpen voor het selectief onderdrukken van uitzonderingen
Maar het lijken wrappers te zijn probeer / behalve / else / eindelijk blokkeert, als [Python 3]: Het with statement luidt:
Hierdoor kunt u algemene proberen…behalve…eindelijk moeten gebruikspatronen worden ingekapseld voor gemakkelijk hergebruik.
-
-
Doorloopfuncties van het bestandssysteem (en zoek in de resultaten naar overeenkomende item(s))
-
[Python 3]: os.listdir (path=’.’) (of [Python 3]: os.scandir(path=’.’) op Python v3.5 +, achterpoort: [PyPI]: scandir)
-
Onder de motorkap gebruiken beide:
- Nix: [man7]: OPENDIR (3) / [man7]: READDIR(3) / [man7]: CLOSEDIR(3)
- Winnen: [MS.Docs]: FindFirstFileW-functie / [MS.Docs]: FindNextFileW-functie / [MS.Docs]: FindClose-functie
via [GitHub]: python/cpython – (master) cpython/ Modules/posixmodule.c
scandir() gebruiken in plaats van listdir() kan de prestaties van code die ook een bestandstype of bestand nodig heeft aanzienlijk verbeteren attribuutinformatie, omdat os.DirEntry-objecten deze informatie vrijgeven als de besturingssysteem biedt het bij het scannen van een map. Alle os.DirEntry-methoden kunnen een systeemaanroep uitvoeren, maar is_dir() en is_file() vereisen meestal alleen een systeemaanroep voor symbolische links; os.DirEntry.stat() vereist altijd een systeem oproep op Unix, maar vereist slechts één voor symbolische links op Windows.
-
- [Python 3]: os.lopen(top, topdown=True, onerror=Geen, followlinks=False)
- Het gebruikt
os.listdir
(os.scandir
indien beschikbaar)
- Het gebruikt
- [Python 3]: glob.iglob(padnaam, *, recursive=False) (of zijn voorganger:
glob.glob
)- Het lijkt per se geen doorkruisende functie (althans in sommige gevallen), maar het gebruikt nog steeds
os.listdir
- Het lijkt per se geen doorkruisende functie (althans in sommige gevallen), maar het gebruikt nog steeds
Aangezien deze mappen doorlopen, zijn ze (in de meeste gevallen) inefficiënt voor ons probleem (er zijn uitzonderingen, zoals niet-jokertekens globbing – zoals @ShadowRanger opmerkte), dus ik ga er niet op aandringen. Om nog maar te zwijgen van het feit dat in sommige gevallen het verwerken van bestandsnamen nodig kan zijn.
-
-
[Python 3]: os.toegang (path, mode, *, dir_fd=None, Effective_ids=False, follow_symlinks=True) wiens gedrag in de buurt komt van
os.path.exists
(eigenlijk is het breder, voornamelijk vanwege het 2de argument)- gebruikersrechten kunnen de “zichtbaarheid” van het bestand beperken, zoals in het document staat:
…test of de aanroepende gebruiker de gespecificeerde toegang heeft tot pad. modus moet F_OK zijn om te testen het bestaan van pad…
os.access("/tmp", os.F_OK)
Omdat ik ook in C werk, gebruik ik deze methode ook omdat het onder de motorkap native APIs aanroept (opnieuw, via “${PYTHON_SRC_DIR}/Modules/posixmodule.c”), maar het opent ook een poort voor mogelijke gebruikersfouten, en het is niet zo Python em>ic als andere varianten. Dus, zoals @AaronHall terecht opmerkte, gebruik het niet tenzij je weet wat je doet:
- Nix: [man7]: TOEGANG (2) (!!! let op de opmerking over het beveiligingslek dat het gebruik ervan kan veroorzaken !!!)
- Winnen: [MS.Docs]: GetFileAttributesW-functie
Opmerking: het aanroepen van native API‘s is ook mogelijk via [Python 3]: ctypes – Een externe functiebibliotheek voor Python, maar in de meeste gevallen is het ingewikkelder.
(Win specifiek): sinds vcruntime* (msvcr*) .dll exporteert een [ MS.Docs]: _access, _waccess ook functiefamilie, hier is een voorbeeld:
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
Opmerkingen:
- Hoewel het geen goede gewoonte is, gebruik ik
os.F_OK
in de aanroep, maar dat is alleen voor de duidelijkheid (de waarde is 0) - Ik gebruik _waccess zodat dezelfde code werkt op Python3 en Python2 (ondanks unicode gerelateerde verschillen tussen hen)
- Hoewel dit op een heel specifiek gebied is gericht, het werd in geen van de eerdere antwoorden genoemd
Ook de Lnx (Ubtu (16 x64)) tegenhanger:
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
Opmerkingen:
-
In plaats daarvan hardcodeert het pad van libc (“/lib/x86_64-linux-gnu/libc.so.6”) dat mogelijk (en hoogstwaarschijnlijk , zal) per systeem verschillen, None (of de lege tekenreeks) kan worden doorgegeven aan de CDLL-constructor (
ctypes.CDLL(None).access(b"/tmp", os.F_OK)
). Volgens [man7]: DLOPEN(3):Als bestandsnaam NULL is, dan is de geretourneerde handle voor de main
programma. Wanneer gegeven aan dlsym(), veroorzaakt deze handle een zoekopdracht naar a
symbool in het hoofdprogramma, gevolgd door alle gedeelde objecten geladen op
programma opstarten, en dan alle gedeelde objecten geladen door dlopen() met
de vlag RTLD_GLOBAL.- Hoofdprogramma (python) is gekoppeld aan libc, dus de symbolen (inclusief toegang) worden geladen
- Hier moet voorzichtig mee worden omgegaan, aangezien functies zoals main, Py_Main en (alle) andere beschikbaar zijn; ze bellen kan rampzalige gevolgen hebben (op het huidige programma)
- Dit geldt niet ook voor Win (maar dat is niet zo erg, aangezien msvcrt.dll zich in “%SystemRoot%\System32 bevindt “ die standaard in %PATH% staat). Ik wilde verder gaan en dit gedrag repliceren op Win (en een patch indienen), maar het blijkt dat [MS.Docs]: GetProcAddress-functie “ziet” alleen geëxporteerde symbolen, dus tenzij iemand verklaart de functies in het hoofduitvoerbare bestand als
__declspec(dllexport)
(waarom zou de gewone persoon dat in vredesnaam doen?), het hoofdprogramma is laadbaar maar vrijwel onbruikbaar
- gebruikersrechten kunnen de “zichtbaarheid” van het bestand beperken, zoals in het document staat:
-
Installeer een module van derden met bestandssysteemmogelijkheden
Hoogstwaarschijnlijk zal een van de bovenstaande manieren worden gebruikt (misschien met kleine aanpassingen).
Een voorbeeld is (opnieuw, Win specifiek) [GitHub]: mhammond/pywin32 – Python voor Windows (pywin32)-extensies, een Python-wrapper over WINAPIs.Maar aangezien dit meer een tijdelijke oplossing is, stop ik hier.
-
Een andere (lame) oplossing (gainarie) is (zoals ik het graag noem) de sysadmin-benadering: gebruik Python als een wrapper om shell-commando’s uit te voeren
-
Winnen:
(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
-
Kortom:
- Gebruik probeer / behalve / else / eindelijk blokken, omdat ze kunnen voorkomen dat je een reeks vervelende problemen tegenkomt. Een tegenvoorbeeld dat ik kan bedenken, zijn prestaties: zulke blokken zijn duur, dus probeer ze niet in code te plaatsen die honderdduizenden keren per seconde zou moeten draaien (maar aangezien het (in de meeste gevallen) schijftoegang betreft, dat zal niet het geval zijn).
Laatste opmerking(en):
- Ik zal proberen het up-to-date te houden, alle suggesties zijn welkom, ik zal alles wat nuttig is, opnemen in het antwoord
Antwoord 8, autoriteit 3%
Python 3.4+ heeft een objectgeoriënteerde padmodule: pathlib. Met behulp van deze nieuwe module kunt u controleren of een bestand als volgt bestaat:
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
Je kunt (en moet) nog steeds een try/except
-blok gebruiken bij het openen van bestanden:
try:
with p.open() as f:
# do awesome stuff
except OSError:
print('Well darn.')
De pathlib-module bevat veel coole dingen: handig globbing, de eigenaar van een bestand controleren, gemakkelijker paden toevoegen, enz. Het is de moeite van het bekijken waard. Als je een oudere Python gebruikt (versie 2.6 of hoger), kun je pathlib nog steeds installeren met pip:
# installs pathlib2 on older Python versions
# the original third-party module, pathlib, is no longer maintained.
pip install pathlib2
Importeer het dan als volgt:
# Older Python versions
import pathlib2 as pathlib
Antwoord 9, autoriteit 3%
Dit is de eenvoudigste manier om te controleren of een bestand bestaat. Alleen omdat het bestand al bestond toen u het aanvinkte, garandeert niet dat het er zal zijn wanneer u het moet openen.
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")
Antwoord 10, autoriteit 2%
Geef de voorkeur aan het try-statement. Het wordt beschouwd als een betere stijl en vermijdt raceomstandigheden.
Geloof me niet op mijn woord. Er is voldoende steun voor deze theorie. Hier is een paar:
- Stijl: sectie “Omgaan met ongebruikelijke omstandigheden” van http://allendowney.com/sd/notes /notes11.txt
- Racevoorwaarden vermijden
Antwoord 11, autoriteit 2%
Hoe controleer ik of een bestand bestaat, met Python, zonder een try-statement te gebruiken?
Nu beschikbaar sinds Python 3.4, importeer en instantiëer een Path
-object met de bestandsnaam, en controleer de is_file
-methode (merk op dat dit True retourneert voor symbolische links die verwijzen naar normaal bestanden ook):
>>> from pathlib import Path
>>> Path('/').is_file()
False
>>> Path('/initrd.img').is_file()
True
>>> Path('/doesnotexist').is_file()
False
Als je Python 2 gebruikt, kun je de pathlib-module backporten vanuit pypi, pathlib2
, of vink anders isfile
aan in de module os.path
:
>>> import os
>>> os.path.isfile('/')
False
>>> os.path.isfile('/initrd.img')
True
>>> os.path.isfile('/doesnotexist')
False
Het bovenstaande is waarschijnlijk het beste pragmatische directe antwoord hier, maar er is de mogelijkheid van een race-conditie (afhankelijk van wat je probeert te bereiken), en het feit dat de onderliggende implementatie een try
, maar Python gebruikt overal in de implementatie try
.
Omdat Python overal try
gebruikt, is er echt geen reden om een implementatie die het gebruikt te vermijden.
Maar de rest van dit antwoord probeert deze kanttekeningen in overweging te nemen.
Langer, veel pedanter antwoord
Beschikbaar sinds Python 3.4, gebruik het nieuwe Path
-object in pathlib
. Merk op dat .exists
niet helemaal juist is, omdat mappen geen bestanden zijn (behalve in de unix-zin dat alles een bestand is).
>>> from pathlib import Path
>>> root = Path('/')
>>> root.exists()
True
We moeten dus is_file
gebruiken:
>>> root.is_file()
False
Hier is de hulp op is_file
:
is_file(self)
Whether this path is a regular file (also True for symlinks pointing
to regular files).
Dus laten we een bestand nemen waarvan we weten dat het een bestand is:
>>> import tempfile
>>> file = tempfile.NamedTemporaryFile()
>>> filepathobj = Path(file.name)
>>> filepathobj.is_file()
True
>>> filepathobj.exists()
True
Standaard verwijdert NamedTemporaryFile
het bestand wanneer het wordt gesloten (en wordt automatisch gesloten wanneer er geen verwijzingen meer naar bestaan).
>>> del file
>>> filepathobj.exists()
False
>>> filepathobj.is_file()
False
Als u zich echter verdiept in de implementatie , zul je zien dat is_file
try
gebruikt:
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
Racevoorwaarden: waarom we graag proberen
We houden van try
omdat het raceomstandigheden vermijdt. Met try
probeer je gewoon je bestand te lezen, in de verwachting dat het daar is, en zo niet, dan vang je de uitzondering en voer je elk logisch terugvalgedrag uit.
Als je wilt controleren of een bestand bestaat voordat je het probeert te lezen, en je zou het kunnen verwijderen en dan zou je meerdere threads of processen kunnen gebruiken, of een ander programma weet van dat bestand en zou het kunnen verwijderen – je loopt het risico de kans op een racevoorwaarde als je controleert of deze bestaat, omdat je dan racet om deze te openen voordat de voorwaarde (het bestaan ervan) verandert.
Race-omstandigheden zijn erg moeilijk te debuggen omdat er een heel klein venster is waarin ze ervoor kunnen zorgen dat je programma faalt.
Maar als dit je motivatie is, kunt de waarde van een try
-statement krijgen door de contextmanager suppress
te gebruiken.
Racevoorwaarden vermijden zonder een try-statement: suppress
Python 3.4 geeft ons de suppress
contextmanager (voorheen de ignore
contextmanager), die semantisch precies hetzelfde in minder regels, terwijl het ook (althans oppervlakkig) voldoet aan de oorspronkelijke vraag om een try
-statement te vermijden:
from contextlib import suppress
from pathlib import Path
Gebruik:
>>> with suppress(OSError), Path('doesnotexist').open() as f:
... for line in f:
... print(line)
...
>>>
>>> with suppress(OSError):
... Path('doesnotexist').unlink()
...
>>>
Voor eerdere Pythons zou je je eigen suppress
kunnen rollen, maar zonder een try
zal het uitgebreider zijn dan met. Ik geloof echt dat dit eigenlijk het enige antwoord is dat try
op geen enkel niveau in de Python gebruikt dat kan worden toegepast op vóór Python 3.4, omdat het een contextmanager gebruikt in plaats daarvan:
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)
Misschien makkelijker met een poging:
from contextlib import contextmanager
@contextmanager
def suppress(*exceptions):
try:
yield
except exceptions:
pass
Andere opties die niet voldoen aan de vraag naar “zonder proberen”:
isfile
import os
os.path.isfile(path)
uit de docs:
os.path.isfile(path)
Retourneer True als pad een bestaand regulier bestand is. Dit volgt symbolisch
links, dus zowelislink()
alsisfile()
kunnen waar zijn voor hetzelfde pad.
Maar als je de bron hiervan bekijkt functie, zult u zien dat het inderdaad een try-statement gebruikt:
# 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
Het enige wat het doet, is het opgegeven pad gebruiken om te zien of het er statistieken over kan krijgen, OSError
opvangen en vervolgens controleren of het een bestand is als het de uitzondering niet heeft veroorzaakt.
Als je van plan bent iets met het bestand te doen, raad ik je aan om het direct te proberen met een try-behalve om een raceconditie te voorkomen:
try:
with open(path) as f:
f.read()
except OSError:
pass
os.access
Beschikbaar voor Unix en Windows is os.access
, maar om te gebruiken moet je vlaggen doorgeven, en het maakt geen onderscheid tussen bestanden en mappen. Dit wordt meer gebruikt om te testen of de echte aanroepende gebruiker toegang heeft in een omgeving met verhoogde bevoegdheden:
import os
os.access(path, os.F_OK)
Het lijdt ook aan dezelfde raceconditieproblemen als isfile
. Uit de docs:
Opmerking:
Gebruik access() om te controleren of een gebruiker geautoriseerd is om b.v. Een bestand openen
voordat u dit daadwerkelijk doet, maakt het gebruik van open() een beveiligingslek, omdat
de gebruiker kan misbruik maken van het korte tijdsinterval tussen het controleren en
het bestand openen om het te manipuleren. Het verdient de voorkeur om EAFP . te gebruiken
technieken. Bijvoorbeeld:if os.access("myfile", os.R_OK): with open("myfile") as fp: return fp.read() return "some default data"
is beter geschreven 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()
Vermijd het gebruik van os.access
. Het is een functie op een laag niveau die meer kans heeft op gebruikersfouten dan de objecten en functies op een hoger niveau die hierboven zijn besproken.
Kritiek op een ander antwoord:
Een ander antwoord zegt dit over os.access
:
Persoonlijk geef ik hier de voorkeur aan omdat het onder de motorkap native API’s aanroept (via “${PYTHON_SRC_DIR}/Modules/posixmodule.c”), maar het opent ook een poort voor mogelijke gebruikersfouten, en het is niet zo Pythonic zoals andere varianten:
Dit antwoord zegt dat het de voorkeur geeft aan een niet-pythonische, foutgevoelige methode, zonder rechtvaardiging. Het lijkt gebruikers aan te moedigen om low-level API’s te gebruiken zonder ze te begrijpen.
Het creëert ook een contextmanager die, door onvoorwaardelijk True
terug te geven, alle uitzonderingen (inclusief KeyboardInterrupt
en SystemExit
!) stil laat passeren , wat een goede manier is om bugs te verbergen.
Dit lijkt gebruikers aan te moedigen slechte praktijken toe te passen.
Antwoord 12, autoriteit 2%
Testen op bestanden en mappen met os.path.isfile()
, os.path.isdir()
en os.path.exists()
Ervan uitgaande dat het “pad” een geldig pad is, laat deze tabel zien wat elke functie voor bestanden en mappen teruggeeft:
Je kunt ook testen of een bestand een bepaald type bestand is door os.path.splitext()
te gebruiken om de extensie te krijgen (als je die nog niet weet)
>>> 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
Antwoord 13, autoriteit 2%
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!"
Het importeren van os
maakt het gemakkelijker om met uw besturingssysteem te navigeren en standaardacties uit te voeren.
Zie voor referentie ook Hoe te controleren of een bestand bestaat met Python?
Als je bewerkingen op hoog niveau nodig hebt, gebruik dan shutil
.
Antwoord 14
In 2016 is de beste manier nog steeds om os.path.isfile
te gebruiken:
>>> os.path.isfile('/path/to/some/file.txt')
Of in Python 3 kun je pathlib
gebruiken:
import pathlib
path = pathlib.Path('/path/to/some/file.txt')
if path.is_file():
...
Antwoord 15
Het lijkt erop dat er geen betekenisvol functioneel verschil is tussen try/behalve en isfile()
, dus je moet gebruiken welke zinvol is.
Als je een bestand wilt lezen, als het bestaat, doe dan
try:
f = open(filepath)
except IOError:
print 'Oh dear.'
Maar als u alleen een bestand wilt hernoemen als het bestaat en het daarom niet hoeft te openen, doe dat dan
if os.path.isfile(filepath):
os.rename(filepath, filepath + '.old')
Als je naar een bestand wilt schrijven, als het niet bestaat, doe dan
# 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'
Als je bestandsvergrendeling nodig hebt, is dat een andere zaak.
Antwoord 16
Je zou dit (veiliger) kunnen proberen:
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))
De output zou zijn:
([Errno 2] Geen dergelijk bestand of map:
‘whatever.txt’)
Vervolgens, afhankelijk van het resultaat, kan je programma vanaf daar gewoon doorgaan of je kunt coderen om het te stoppen als je wilt.
Antwoord 17
Datum: 2017-12-04
Elke mogelijke oplossing is vermeld in andere antwoorden.
Een intuïtieve en betwistbare manier om te controleren of een bestand bestaat, is de volgende:
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')
Ik heb een uitgebreide cheatsheet gemaakt ter referentie:
#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']}
Antwoord 18
Hoewel ik altijd aanraad om try
en except
statements te gebruiken, zijn hier een paar mogelijkheden voor jou (mijn persoonlijke favoriet is het gebruik van os.access
):
-
Probeer het bestand te openen:
Als u het bestand opent, wordt altijd het bestaan van het bestand gecontroleerd. Je kunt een functie net zo maken:
def File_Existence(filepath): f = open(filepath) return True
Als het False is, stopt het de uitvoering met een onhandige IOError
of OSError in latere versies van Python. Om de uitzondering te vangen,
je moet een try-behalve-clausule gebruiken. Dat kan natuurlijk altijd
gebruik eentry
behalve`-instructie zoals deze (dankzij hsandt
om me aan het denken te zetten):def File_Existence(filepath): try: f = open(filepath) except IOError, OSError: # Note OSError is for later versions of Python return False return True
-
Gebruik
os.path.exists(path)
:Hiermee wordt het bestaan gecontroleerd van wat u opgeeft. Het controleert echter op bestanden en mappen, dus pas op hoe u het gebruikt.
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
-
Gebruik
os.access(path, mode)
:Hierdoor wordt gecontroleerd of u toegang heeft tot het bestand. Het zal controleren op toestemmingen. Op basis van de os.py-documentatie, door
os.F_OK
in te typen, wordt het bestaan van het pad gecontroleerd. Als u dit gebruikt, ontstaat er echter een beveiligingslek, omdat iemand uw bestand kan aanvallen met behulp van de tijd tussen het controleren van de machtigingen en het openen van het bestand. U moet in plaats daarvan rechtstreeks naar het openen van het bestand gaan in plaats van de machtigingen te controleren. (EAFP versus LBYP). Als u het bestand daarna niet opent en alleen het bestaan ervan controleert, kunt u dit gebruiken.Hoe dan ook, hier:
>>> import os >>> os.access("/is/a/file.txt", os.F_OK) True
Ik moet ook vermelden dat er twee manieren zijn waarop u het bestaan van een bestand niet kunt verifiëren. Ofwel is het probleem permission denied
of no such file or directory
. Als u een IOError
opvangt, stelt u de IOError as e
(zoals mijn eerste optie), en typt u vervolgens print(e.args)
dus dat u hopelijk uw probleem kunt bepalen. Ik hoop dat het helpt! 🙂
Antwoord 19
Bovendien os.access()
:
if os.access("myfile", os.R_OK):
with open("myfile") as fp:
return fp.read()
R_OK
, W_OK
en X_OK
de vlaggen zijn om te testen op machtigingen (doc).
Antwoord 20
Als het bestand bedoeld is om te openen, kunt u een van de volgende technieken gebruiken:
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!')
UPDATE
Om verwarring te voorkomen en op basis van de antwoorden die ik heb gekregen, vindt het huidige antwoord een bestand of een map met de opgegeven naam.
Antwoord 21
De gemakkelijkste manier om dit te doen is met
import os
if os.path.exists(FILE):
# file exists
pass
else:
# file does not exists
pass
uit de os-bibliotheek, terwijl FILE het relatieve pad is. In Windows kan dit al dan niet werken en moet u mogelijk het absolutiepad gebruiken door os.path.exists(os.path.join(os.path.abspath('./'), FILE))
, waarbij FILE nog steeds het relatieve pad plus bestandsnaam is
Antwoord 22
TL;DR met een enkele regel code — Keep It Simple
Gebruik de module Pad om het bestaan van een bestand of een map te controleren.
from pathlib import Path
if Path("myfile.txt").exists(): # works for both file and folders
# do stuffs...
De pathlib
-module is geïntroduceerd in Python 3.4
, dus je moet Python 3.4+ hebben, deze lib maakt je leven veel gemakkelijker en het is mooi om te gebruiken, hier is er meer documentatie over (https://docs.python.org/3/library/pathlib .html).
BTW, als je het pad gaat hergebruiken, dan is het beter om het toe te wijzen aan een variabele
zo wordt het
from pathlib import Path
p = Path("loc/of/myfile.txt")
if p.exists(): # works for both file and folders
# do stuffs...
Antwoord 23
if os.path.isfile(path_to_file):
try:
open(path_to_file)
pass
except IOError as e:
print "Unable to open file"
Het verhogen van uitzonderingen wordt beschouwd als een acceptabele, en Pythonische,
aanpak voor flow control in uw programma. Overweeg afhandeling ontbreekt
bestanden met IOErrors. In deze situatie zal een IOError-uitzondering zijn:
verhoogd als het bestand bestaat maar de gebruiker geen leesrechten heeft.
SRC: http://www.pfinn.net/python-check-if-file -bestaat.html
Antwoord 24
Als je NumPy al voor andere doeleinden hebt geïmporteerd, is het niet nodig om andere bibliotheken te importeren, zoals pathlib
, os
, paths
, enz.
import numpy as np
np.DataSource().exists("path/to/your/file")
Dit zal waar of onwaar retourneren op basis van het bestaan ervan.
Antwoord 25
U kunt os.path.exists() :
. gebruiken
import os
print(os.path.exists("file"))
Hoop dat het helpt 😀
Antwoord 26
Je kunt Brian’s suggestie schrijven zonder de try:
.
from contextlib import suppress
with suppress(IOError), open('filename'):
process()
suppress
is onderdeel van Python 3.4. In oudere releases kun je snel je eigen onderdrukking schrijven:
from contextlib import contextmanager
@contextmanager
def suppress(*exceptions):
try:
yield
except exceptions:
pass
Antwoord 27
Controleer of het bestand of de map bestaat
Je kunt deze drie manieren volgen:
Opmerking1: De
os.path.isfile
wordt alleen voor bestanden gebruikt
import os.path
os.path.isfile(filename) # True if file exists
os.path.isfile(dirname) # False if directory exists
Opmerking2: De
os.path.exists
die wordt gebruikt voor zowel bestanden als mappen
import os.path
os.path.exists(filename) # True if file exists
os.path.exists(dirname) #True if directory exists
De
pathlib.Path
methode (inbegrepen in Python 3+, installeerbaar met pip voor Python 2)
from pathlib import Path
Path(filename).exists()
Antwoord 28
Nog een kleine variatie toevoegen die niet precies wordt weerspiegeld in de andere antwoorden.
Dit behandelt het geval dat file_path
None
of een lege tekenreeks is.
def file_exists(file_path):
if not file_path:
return False
elif not os.path.isfile(file_path):
return False
else:
return True
Een variant toevoegen op basis van suggestie van Shahbaz
def file_exists(file_path):
if not file_path:
return False
else:
return os.path.isfile(file_path)
Een variant toevoegen op basis van suggestie van Peter Wood
def file_exists(file_path):
return file_path and os.path.isfile(file_path):
Antwoord 29
Ik ben de auteur van een pakket dat al ongeveer 10 jaar bestaat, en het heeft een functie die deze vraag rechtstreeks aanpakt. Kortom, als je op een niet-Windows-systeem werkt, gebruikt het Popen
om toegang te krijgen tot find
. Als u echter Windows gebruikt, repliceert het find
met een efficiënte bestandssysteem-walker.
De code zelf maakt geen gebruik van een try
-blok behalve bij het bepalen van het besturingssysteem en om u zo naar de “Unix”-achtige find
of de met de hand gebouwde find
. Timingtests toonden aan dat de try
sneller was bij het bepalen van het besturingssysteem, dus ik gebruikte er een daar (maar nergens anders).
>>> import pox
>>> pox.find('*python*', type='file', root=pox.homedir(), recurse=False)
['/Users/mmckerns/.python']
En het document
>>> 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']
>>>
De implementatie, als je wilt kijken, is hier:
https://github.com/uqfoundation/pox/blob/89ffacab308f2872ca738a308f2872ca738a308f2872ca738a308 /pox/shutils.py#L190
Antwoord 30
Hier is een 1-regelige Python-opdracht voor de Linux-opdrachtregelomgeving. Ik vind dit ERG HANDIG omdat ik niet zo’n hete Bash-man ben.
python -c "import os.path; print os.path.isfile('/path_to/file.xxx')"
Ik hoop dat dit nuttig is.