Hoe controleer ik of een bestand bestaat zonder uitzonderingen?

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:

  1. Controleer bestand (betwistbaar: ook map (“speciaal” bestand)?) bestaan
  2. Niet gebruiken probeer / behalve / anders / eindelijk blokken

Mogelijke oplossingen:

  1. [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. Retourneert False voor verbroken symbolische links. Op sommige platforms kan deze functie False 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.pathposixpath.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
      
  2. [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 proberenbehalveeindelijk moeten gebruikspatronen worden ingekapseld voor gemakkelijk hergebruik.

  3. Doorloopfuncties van het bestandssysteem (en zoek in de resultaten naar overeenkomende item(s))

    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.

  4. [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:

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

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


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 zowel islink() als isfile() 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:

enter afbeelding beschrijving hier

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

  1. 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 een try 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
    
  2. 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
    
  3. 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.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

five × 4 =

Other episodes