Comment vérifier si un fichier existe sans exception?

Réponses:

5156

Si la raison pour laquelle vous vérifiez est que vous pouvez faire quelque chose comme if file_exists: open_it(), il est plus sûr d'utiliser un tryautour pour tenter de l'ouvrir. La vérification puis l'ouverture risquent de supprimer ou de déplacer le fichier ou quelque chose entre le moment où vous vérifiez et le moment où vous essayez de l'ouvrir.

Si vous ne prévoyez pas d'ouvrir le fichier immédiatement, vous pouvez utiliser os.path.isfile

Renvoie Truesi le chemin est un fichier standard existant. Cela suit les liens symboliques, donc islink () et isfile () peuvent être vrais pour le même chemin.

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

si vous devez être sûr que c'est un fichier.

À partir de Python 3.4, le pathlibmodule propose une approche orientée objet (rétroportée pathlib2en Python 2.7):

from pathlib import Path

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

Pour vérifier un répertoire, procédez comme suit:

if my_file.is_dir():
    # directory exists

Pour vérifier si un Pathobjet existe indépendamment du fait qu'il s'agisse d'un fichier ou d'un répertoire, utilisez exists():

if my_file.exists():
    # path exists

Vous pouvez également utiliser resolve(strict=True)dans un trybloc:

try:
    my_abs_path = my_file.resolve(strict=True)
except FileNotFoundError:
    # doesn't exist
else:
    # exists
rslite
la source
40
concernant la première remarque (utilisez "essayer" si cochez avant d'ouvrir) malheureusement cela ne fonctionnera pas si vous voulez ouvrir pour ajouter en étant sûr qu'il existe avant puisque le mode 'a' créera s'il n'existe pas.
makapuf
6
Notez que cela a FileNotFoundErrorété introduit dans Python 3. Si vous devez également prendre en charge Python 2.7 ainsi que Python 3, vous pouvez utiliser à la IOErrorplace (quelles FileNotFoundErrorsous-classes) stackoverflow.com/a/21368457/1960959
scottclowe
7
@makapuf Vous pouvez l'ouvrir pour la "mise à jour" ( open('file', 'r+')) puis rechercher jusqu'à la fin.
kyrill
2111

Vous avez la os.path.existsfonction:

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

Cela renvoie Trueà la fois pour les fichiers et les répertoires mais vous pouvez utiliser à la place

os.path.isfile(file_path)

pour tester si c'est un fichier en particulier. Il suit les liens symboliques.

PierreBdR
la source
966

Contrairement isfile(), exists()reviendra Truepour les répertoires. Donc, selon que vous souhaitez uniquement des fichiers simples ou également des répertoires, vous utiliserez isfile()ou exists(). Voici une sortie REPL simple:

>>> 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
bortzmeyer
la source
623
import os.path

if os.path.isfile(filepath):
Paul
la source
320

Utiliser os.path.isfile()avec 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")
Yugal Jindle
la source
60
avoir des conditions multiples, dont certaines sont superflues, est moins clair et explicite.
wim
10
Il est également redondant. Si le fichier n'existe pas, os.access()renvoie false.
Marquis de Lorne
9
@EJP Dans Linux, les fichiers peuvent exister mais ne sont pas accessibles.
e-info128
8
puisque vous import os, vous n'en avez plus besoin import os.pathcar il en fait déjà partie os. Vous avez juste besoin d'importer os.pathsi vous n'utilisez que des fonctions depuis os.pathet non de oslui-même, pour importer une chose plus petite, mais comme vous utilisez os.accesset os.R_OK, la deuxième importation n'est pas nécessaire.
Jester
287
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
bienfaiteur
la source
2
En règle générale, il n'est pas recommandé de nommer les variables de la même manière que les noms de méthode.
Homunculus Reticulli
245

Bien que presque toutes les manières possibles aient été répertoriées dans (au moins une des) réponses existantes (par exemple, des éléments spécifiques à Python 3.4 ont été ajoutés), je vais essayer de tout regrouper.

Remarque : chaque morceau de code de bibliothèque standard Python que je vais publier appartient à la version 3.5.3 .

Énoncé du problème :

  1. Vérifier l' existence du fichier ( défendable : également le dossier (fichier "spécial")?)
  2. N'utilisez pas les blocs try / except / else / finally

Solutions possibles :

  1. [Python 3]: os.path. EXISTE ( chemin ) (vérifier également d' autres membres de la famille des fonctions comme os.path.isfile, os.path.isdir, os.path.lexistsdes comportements légèrement différents)

    os.path.exists(path)

    Renvoie Truesi chemin fait référence à un chemin existant ou à un descripteur de fichier ouvert. Renvoie Falseles liens symboliques rompus. Sur certaines plates-formes, cette fonction peut retourner Falsesi l'autorisation n'est pas accordée pour exécuter os.stat () sur le fichier demandé, même si le chemin existe physiquement.

    Tout va bien, mais si vous suivez l'arborescence d'importation:

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

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

    c'est juste un bloc try / except autour de [Python 3]: os. stat ( path, *, dir_fd = None, follow_symlinks = True ) . Donc, votre code est try / except free, mais plus bas dans la framestack il y a (au moins) un tel bloc. Cela s'applique également à d'autres fonctions ( y compris os.path.isfile ).

    1.1. [Python 3]: Chemin. is_file ()

    • C'est une façon plus sophistiquée (et plus python ic) de gérer les chemins, mais
    • Sous le capot, il fait exactement la même chose ( pathlib.py , ligne ~ # 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]: avec les gestionnaires de contexte d'instruction . Soit:

    • Créer une:

      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 ...)
      • Et son utilisation - je vais reproduire le os.path.isfilecomportement (notez que c'est juste à des fins de démonstration, n'essayez pas d'écrire un tel code pour la production ):

        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
    • Utilisez [Python 3]: contextlib. supprimer ( * exceptions ) - qui a été spécialement conçu pour supprimer sélectivement les exceptions


    Mais, ils semblent être des wrappers sur les blocs try / except / else / finally , comme [Python 3]: L' instruction with indique:

    Cela permet d' essayer ... sauf ... enfin, les modèles d'utilisation à encapsuler pour une réutilisation pratique.

  3. Fonctions de traversée du système de fichiers (et recherchez les éléments correspondants dans les résultats)


    Étant donné que ces itérations sur les dossiers, (dans la plupart des cas), elles sont inefficaces pour notre problème (il existe des exceptions, comme le glob bing non générique - comme l'a souligné @ShadowRanger), donc je ne vais pas insister sur eux. Sans oublier que dans certains cas, le traitement des noms de fichiers peut être requis.

  4. [Python 3]: os. access ( path, mode, *, dir_fd = None, effective_ids = False, follow_symlinks = True ) dont le comportement est proche os.path.exists(en fait, il est plus large, principalement à cause du 2 ème argument)

    • les autorisations des utilisateurs peuvent restreindre la "visibilité" du fichier comme l'indique le document:

      ... teste si l'utilisateur appelant a l'accès spécifié au chemin . le mode devrait être F_OK pour tester l'existence du chemin ...

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

    Depuis que je aussi travailler en C , j'utilise cette méthode ainsi que sous le capot, il appelle native API s (encore une fois, par « $ {} PYTHON_SRC_DIR /Modules/posixmodule.c » ), mais il ouvre aussi une porte pour un éventuel utilisateur erreurs , et ce n'est pas aussi Python ic que les autres variantes. Donc, comme @AaronHall l'a souligné à juste titre, ne l'utilisez que si vous savez ce que vous faites:

    Remarque : appeler des API natives est également possible via [Python 3]: ctypes - Une bibliothèque de fonctions étrangères pour Python , mais dans la plupart des cas, c'est plus compliqué.

    ( Spécifique à Win ): Étant donné que vcruntime * ( msvcr * ) .dll exporte également une famille de fonctions [MS.Docs]: _access, _waccess , voici un exemple:

    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

    Remarques :

    • Bien que ce ne soit pas une bonne pratique, j'utilise os.F_OKdans l'appel, mais c'est juste pour plus de clarté (sa valeur est 0 )
    • J'utilise _waccess pour que le même code fonctionne sur Python3 et Python2 (malgré les différences liées à l' unicode entre eux)
    • Bien que cela cible un domaine très spécifique, il n'a été mentionné dans aucune des réponses précédentes


    La contrepartie Lnx ( Ubtu (16 x64) ) également:

    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

    Remarques :

    • Au lieu de cela, codez en dur le chemin de libc ( "/lib/x86_64-linux-gnu/libc.so.6" ) qui peut (et très probablement, variera) d'un système à l'autre, Aucun (ou la chaîne vide) peut être transmis au constructeur CDLL ( ctypes.CDLL(None).access(b"/tmp", os.F_OK)). Selon [man7]: DLOPEN (3) :

      Si le nom de fichier est NULL, le descripteur renvoyé correspond au programme principal. Lorsqu'il est donné à dlsym (), ce handle provoque une recherche d'un symbole dans le programme principal, suivi de tous les objets partagés chargés au démarrage du programme, puis de tous les objets partagés chargés par dlopen () avec l'indicateur RTLD_GLOBAL .

      • Le programme principal (actuel) ( python ) est lié à libc , donc ses symboles (y compris l' accès ) seront chargés
      • Cela doit être géré avec précaution, car des fonctions comme main , Py_Main et (toutes les) autres sont disponibles; les appeler pourrait avoir des effets désastreux (sur le programme actuel)
      • Cela ne s'applique pas également à Win (mais ce n'est pas si grave, car msvcrt.dll est situé dans "% SystemRoot% \ System32" qui est dans % PATH% par défaut). Je voulais aller plus loin et reproduire ce comportement sur Win (et soumettre un correctif), mais il s'avère que [MS.Docs]: la fonction GetProcAddress ne "voit" que les symboles exportés , donc à moins que quelqu'un ne déclare les fonctions dans l'exécutable principal comme __declspec(dllexport)(pourquoi diable la personne ordinaire ferait ça?), le programme principal est chargeable mais quasiment inutilisable
  5. Installer un module tiers avec des capacités de système de fichiers

    Très probablement, s'appuiera sur l'une des méthodes ci-dessus (peut-être avec de légères personnalisations).
    Un exemple serait (encore une fois, spécifique à Win ) [GitHub]: mhammond / pywin32 - Extensions Python pour Windows (pywin32) , qui est un wrapper Python sur les WINAPI .

    Mais, puisque cela ressemble plus à une solution de contournement, je m'arrête ici.

  6. Une autre solution (boiteuse) ( gainarie ) est (comme j'aime l'appeler) l' approche sysadmin : utiliser Python comme wrapper pour exécuter des commandes shell

    • Gagner :

      (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

Conclusion :

  • Ne utiliser essayer / excepter / autre / enfin des blocs, car ils peuvent vous empêcher de courir dans une série de problèmes désagréables. Un contre-exemple auquel je peux penser est la performance: de tels blocs sont coûteux, alors essayez de ne pas les placer dans du code qui est censé s'exécuter des centaines de milliers de fois par seconde (mais puisque (dans la plupart des cas) cela implique un accès au disque, ce ne sera pas le cas).

Note (s) finale (s) :

  • Je vais essayer de le garder à jour, toutes les suggestions sont les bienvenues, j'intégrerai tout ce qui sera utile dans la réponse
CristiFati
la source
3
Pouvez-vous développer cette déclaration? "Bien que ce ne soit pas une bonne pratique, j'utilise os.F_OK dans l'appel, mais c'est juste pour plus de clarté (sa valeur est 0)"
sk8asd123
6
@ sk8asd123: Un peu difficile à faire dans un commentaire: généralement, il est préférable d'utiliser des constantes avec des fonctions qui les accompagnent. Cela s'applique lorsque vous travaillez avec plusieurs modules qui définissent la même constante, car certains peuvent ne pas être à jour et il est préférable que les fonctions et les constantes soient synchronisées. Lorsque je travaille avec des ctypes (appelant directement les fonctions), j'aurais dû définir la constante (à partir de MSDN ), ou ne pas utiliser de constante du tout. C'est juste une directive que j'utilise, à 99,9% cela ne fait probablement aucune différence (fonctionnellement).
CristiFati
3
@CristiFati: à partir de 3.6, glob.iglob(et glob.globaussi) sont basés suros.scandir , donc c'est paresseux maintenant; pour obtenir le premier hit dans un répertoire de 10 millions de fichiers, vous scannez uniquement jusqu'à ce que vous atteigniez le premier hit. Et même avant la version 3.6, si vous utilisez des globméthodes sans caractères génériques, la fonction est intelligente: elle sait que vous ne pouvez avoir qu'un seul hit, ce qui simplifie le globbing à juste os.path.isdirouos.path.lexists (selon que le chemin se termine /).
ShadowRanger
3
Cette deuxième partie de mon commentaire (le remplacement non générique n'itère pas réellement le dossier, et ne l'a jamais fait) signifie que c'est une solution parfaitement efficace au problème (plus lente que d'appeler directement os.path.isdirou os.path.lexistpuisqu'il s'agit d'un groupe d'appels de fonction de niveau Python et d'une chaîne avant de décider que le chemin efficace est viable, mais aucun appel système supplémentaire ni travail d'E / S, ce qui est beaucoup plus lent).
ShadowRanger
154

C'est le moyen le plus simple de vérifier si un fichier existe. Le fait que le fichier existait lorsque vous avez vérifié ne garantit pas qu'il sera là lorsque vous aurez besoin de l'ouvrir.

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")
un33k
la source
17
Tant que vous avez l'intention d'accéder au fichier, la condition de concurrence critique existe , quelle que soit la façon dont votre programme est construit. Votre programme ne peut garantir qu'un autre processus sur l'ordinateur n'a pas modifié le fichier. C'est ce que Eric Lippert appelle une exception exogène . Vous ne pouvez pas l'éviter en vérifiant au préalable l'existence du fichier.
Isaac Supeene
@IsaacSupeene La meilleure pratique consiste à réduire la taille de la fenêtre d'opération (fichier), suivie d'une gestion correcte des exceptions
un33k
145

Python 3.4+ possède un module de chemin orienté objet: pathlib . En utilisant ce nouveau module, vous pouvez vérifier si un fichier existe comme ceci:

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

Vous pouvez (et devez généralement) toujours utiliser un try/exceptbloc lors de l'ouverture de fichiers:

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

Le module pathlib contient beaucoup de choses intéressantes: globbing pratique, vérification du propriétaire du fichier, jointure de chemin plus facile, etc. Cela vaut la peine d'être vérifié. Si vous utilisez un ancien Python (version 2.6 ou ultérieure), vous pouvez toujours installer pathlib avec pip:

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

Importez-le ensuite comme suit:

# Older Python versions
import pathlib2 as pathlib
Cody Piersall
la source
124

Préférez l'instruction try. Il est considéré comme un meilleur style et évite les conditions de course.

Ne me croyez pas sur parole. Il y a beaucoup de soutien pour cette théorie. En voici deux:

pkoch
la source
3
Veuillez ajouter de meilleures sources pour appuyer votre déclaration.
BlueTrin
11
Le lien Éviter les conditions de course (support Apple Dev) cité ne prend pas en charge votre réponse. Cela concerne uniquement l'utilisation de fichiers temporaires contenant des informations sensibles sur des systèmes d'exploitation mal conçus qui ne mettent pas correctement en sandbox des fichiers / répertoires temporaires via des autorisations restreintes. L'utilisation try...exceptne permet pas de résoudre ce problème de toute façon.
jstine
Le problème avec cette méthode, c'est que si vous avez un morceau de code important en fonction du fichier non existant, le mettre dans la except:clause fera qu'une exception apparaissant dans cette partie de votre code lèvera un message déroutant (deuxième erreur levée pendant le traitement du premier.)
Camion
119

Comment vérifier si un fichier existe, en utilisant Python, sans utiliser une instruction try?

Désormais disponible depuis Python 3.4, importez et instanciez un Pathobjet avec le nom de fichier, et vérifiez la is_fileméthode (notez que cela renvoie True pour les liens symboliques pointant également vers des fichiers normaux):

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

Si vous êtes sur Python 2, vous pouvez rétroporter le module pathlib à partir de pypi pathlib2, ou sinon vérifier à isfilepartir du os.pathmodule:

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

Maintenant, ce qui précède est probablement la meilleure réponse directe pragmatique ici, mais il y a la possibilité d'une condition de concurrence (en fonction de ce que vous essayez d'accomplir) et du fait que l'implémentation sous-jacente utilise un try, mais Python utilise trypartout dans son implémentation.

Parce que Python utilise trypartout, il n'y a vraiment aucune raison d'éviter une implémentation qui l'utilise.

Mais le reste de cette réponse tente de tenir compte de ces mises en garde.

Réponse plus longue et beaucoup plus pédante

Disponible depuis Python 3.4, utilisez le nouvel Pathobjet dans pathlib. Notez que ce .existsn'est pas tout à fait raison, car les répertoires ne sont pas des fichiers (sauf dans le sens unix que tout est un fichier).

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

Nous devons donc utiliser is_file:

>>> root.is_file()
False

Voici l'aide sur is_file:

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

Alors, obtenons un fichier que nous savons être un fichier:

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

Par défaut, NamedTemporaryFilesupprime le fichier lorsqu'il est fermé (et se fermera automatiquement lorsqu'il n'y aura plus de références).

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

Si vous creusez dans l'implémentation , vous verrez que cela is_fileutilise 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

Conditions de course: pourquoi nous aimons essayer

On aime tryparce que ça évite les conditions de course. Avec try, vous essayez simplement de lire votre fichier, en vous attendant à ce qu'il soit là, et sinon, vous interceptez l'exception et effectuez le comportement de secours qui a du sens.

Si vous souhaitez vérifier qu'un fichier existe avant d'essayer de le lire, que vous le supprimiez et que vous utilisiez plusieurs threads ou processus, ou qu'un autre programme connaisse ce fichier et puisse le supprimer - vous risquez de une condition de course si vous vérifiez qu'elle existe, car vous êtes alors en course pour l'ouvrir avant que sa condition (son existence) ne change.

Les conditions de concurrence sont très difficiles à déboguer car il existe une très petite fenêtre dans laquelle elles peuvent entraîner l'échec de votre programme.

Mais si telle est votre motivation, vous pouvez obtenir la valeur d'une trydéclaration en utilisant le suppressgestionnaire de contexte.

Éviter les conditions de course sans déclaration d'essai: suppress

Python 3.4 nous donne le suppressgestionnaire de contexte (anciennement le ignoregestionnaire de contexte), qui fait sémantiquement exactement la même chose en moins de lignes, tout en répondant (au moins superficiellement) à la demande d'origine pour éviter une trydéclaration:

from contextlib import suppress
from pathlib import Path

Usage:

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

Pour les Pythons antérieurs, vous pouvez lancer le vôtre suppress, mais sans tryvolonté sera plus verbeux qu'avec. Je crois que c'est en fait la seule réponse qui n'utilise tryà aucun niveau dans Python qui peut être appliquée avant Python 3.4 car elle utilise un gestionnaire de contexte à la place:

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)

Peut-être plus facile avec un essai:

from contextlib import contextmanager

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

Autres options qui ne répondent pas à la demande «sans essayer»:

isfile

import os
os.path.isfile(path)

à partir des documents :

os.path.isfile(path)

Renvoie True si le chemin est un fichier standard existant. Cela suit les liens symboliques, donc les deux islink()et isfile()peuvent être vrais pour le même chemin.

Mais si vous examinez la source de cette fonction, vous verrez qu'elle utilise en fait une instruction 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

Tout ce qu'il fait, c'est utiliser le chemin donné pour voir s'il peut obtenir des statistiques dessus, attraper OSErrorpuis vérifier s'il s'agit d'un fichier s'il n'a pas levé l'exception.

Si vous avez l'intention de faire quelque chose avec le fichier, je vous suggère d'essayer directement avec un essai, sauf pour éviter une condition de concurrence:

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

os.access

Disponible pour Unix et Windows os.access, mais pour l'utiliser, vous devez passer des drapeaux et cela ne fait pas de différence entre les fichiers et les répertoires. Ceci est plus utilisé pour tester si le véritable utilisateur appelant a accès dans un environnement à privilèges élevés:

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

Il souffre également des mêmes problèmes de condition de course que isfile. De la documentation :

Remarque: Utiliser access () pour vérifier si un utilisateur est autorisé par exemple à ouvrir un fichier avant de le faire en utilisant open () crée une faille de sécurité, car l'utilisateur peut exploiter le court intervalle de temps entre la vérification et l'ouverture du fichier pour le manipuler. Il est préférable d'utiliser les techniques EAFP. Par exemple:

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

est mieux écrit comme:

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

Évitez d'utiliser os.access. Il s'agit d'une fonction de bas niveau qui présente plus de possibilités d'erreur utilisateur que les objets et fonctions de niveau supérieur décrits ci-dessus.

Critique d'une autre réponse:

Une autre réponse dit ceci à propos de os.access:

Personnellement, je préfère celui-ci car sous le capot, il appelle des API natives (via "$ {PYTHON_SRC_DIR} /Modules/posixmodule.c"), mais il ouvre également une porte pour d'éventuelles erreurs utilisateur, et ce n'est pas aussi Pythonic que les autres variantes :

Cette réponse indique qu'elle préfère une méthode non pythonique, sujette aux erreurs, sans justification. Il semble encourager les utilisateurs à utiliser des API de bas niveau sans les comprendre.

Il crée également un gestionnaire de contexte qui, en retournant sans condition True, permet à toutes les exceptions (y compris KeyboardInterruptet SystemExit!) De passer silencieusement, ce qui est un bon moyen de masquer les bogues.

Cela semble encourager les utilisateurs à adopter de mauvaises pratiques.

Aaron Hall
la source
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!"

L'importation osfacilite la navigation et l'exécution d'actions standard avec votre système d'exploitation.

Pour référence, voir également Comment vérifier si un fichier existe en utilisant Python?

Si vous avez besoin d'opérations de haut niveau, utilisez shutil.

atlas
la source
9
Cette réponse est fausse. os.path.existsrenvoie true pour les éléments qui ne sont pas des fichiers, tels que les répertoires. Cela donne des faux positifs. Voir les autres réponses qui recommandent os.path.isfile.
Chris Johnson
84

Test des fichiers et des dossiers avec os.path.isfile(), os.path.isdir()etos.path.exists()

En supposant que le «chemin» est un chemin valide, ce tableau montre ce qui est retourné par chaque fonction pour les fichiers et les dossiers:

entrez la description de l'image ici

Vous pouvez également tester si un fichier est un certain type de fichier en utilisant os.path.splitext()pour obtenir l'extension (si vous ne le connaissez pas déjà)

>>> 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
Tom Fuller
la source
72

En 2016, le meilleur moyen est toujours d'utiliser os.path.isfile:

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

Ou en Python 3, vous pouvez utiliser pathlib:

import pathlib
path = pathlib.Path('/path/to/some/file.txt')
if path.is_file():
    ...
KaiBuxe
la source
3
Puis-je demander: Quel est l'avantage d'utiliser le module 'pathlib' au lieu du module 'os' en python3 pour cette vérification?
Joko
3
pathlibest la solution OOP de python pour les chemins. Vous pouvez en faire beaucoup plus. Si vous avez juste besoin de vérifier l'existence, l'avantage n'est pas si grand.
KaiBuxe
65

Il ne semble pas y avoir de différence fonctionnelle significative entre try / except et isfile(), vous devez donc utiliser celle qui a du sens.

Si vous souhaitez lire un fichier, s'il existe, faites

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

Mais si vous voulez simplement renommer un fichier s'il existe et que vous n'avez donc pas besoin de l'ouvrir, faites

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

Si vous voulez écrire dans un fichier, s'il n'existe pas, faites

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

Si vous avez besoin d'un verrouillage de fichier, c'est une autre affaire.

tchad
la source
3
Cette réponse est fausse. os.path.existsrenvoie true pour les éléments qui ne sont pas des fichiers, tels que les répertoires. Cela donne des faux positifs. Voir les autres réponses qui recommandent os.path.isfile.
Chris Johnson
6
Sur votre troisième exemple, je crée un lien nommé filepathavec le bon timing, et BAM , vous écrasez le fichier cible. Vous devriez le faire open(filepath, 'wx')dans un try...exceptbloc pour éviter le problème.
spectras
1
Dans votre deuxième exemple, au moins sous Windows, vous obtiendrez un OSErrorsi filepath + '.old'existe déjà: "Sous Windows, si dst existe déjà, OSError sera déclenchée même s'il s'agit d'un fichier; il n'y a peut-être aucun moyen d'implémenter un renom atomique lorsque dst nomme un fichier existant. "
Tom Myddeltyn
@TomMyddeltyn: Depuis Python 3.3,os.replace effectue de manière portative le remplacement silencieux du fichier de destination (il est identique au os.renamecomportement de Linux) (il ne fait d'erreur que si le nom de destination existe et est un répertoire). Vous êtes donc bloqué sur 2.x, mais les utilisateurs de Py3 ont une bonne option depuis plusieurs années maintenant.
ShadowRanger
Sur l' renameexemple: Cela devrait toujours être fait avec try/ except. os.rename(ou os.replacesur Python moderne) est atomique; le faire vérifier puis renommer introduit une course inutile et des appels système supplémentaires. try: os.replace(filepath, filepath + '.old') except OSError: pass
Faites
59

Vous pouvez essayer ceci (plus sûr):

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

Le résultat serait:

([Errno 2] Aucun fichier ou répertoire de ce type: 'que ce soit.txt')

Ensuite, selon le résultat, votre programme peut simplement continuer à fonctionner à partir de là ou vous pouvez coder pour l'arrêter si vous le souhaitez.

philberndt
la source
18
La question d'origine demandait une solution qui n'utilise pastry
rrs
5
Cette réponse manque le point de l'OP. Vérifier qu'un fichier existe n'est pas la même chose que vérifier si vous pouvez l'ouvrir. Il y aura des cas où un fichier existe, mais pour diverses raisons, vous ne pouvez pas l'ouvrir.
Chris Johnson
51

Bien que je recommande toujours d'utiliser les instructions tryet except, voici quelques possibilités pour vous (mon préféré est d'utiliser os.access):

  1. Essayez d'ouvrir le fichier:

    L'ouverture du fichier vérifiera toujours l'existence du fichier. Vous pouvez créer une fonction comme ceci:

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

    S'il est faux, il arrêtera l'exécution avec une erreur IOError ou OSError non gérée dans les versions ultérieures de Python. Pour intercepter l'exception, vous devez utiliser une clause try except. Bien sûr, vous pouvez toujours utiliser une tryinstruction except comme ceci (merci à hsandt de m'avoir fait réfléchir):

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

    Cela vérifiera l'existence de ce que vous spécifiez. Cependant, il vérifie les fichiers et les répertoires, alors faites attention à la façon dont vous les utilisez.

    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. Utilisation os.access(path, mode):

    Cela vérifiera si vous avez accès au fichier. Il vérifiera les autorisations. Sur la base de la documentation os.py, en tapant os.F_OK, il vérifiera l'existence du chemin. Cependant, son utilisation créera une faille de sécurité, car quelqu'un peut attaquer votre fichier en utilisant le temps entre la vérification des autorisations et l'ouverture du fichier. Vous devriez plutôt aller directement à l'ouverture du fichier au lieu de vérifier ses autorisations. ( EAFP contre LBYP ). Si vous n'ouvrez pas le fichier par la suite et ne vérifiez que son existence, vous pouvez l'utiliser.

    Bref, ici:

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

Je dois également mentionner qu'il existe deux manières de ne pas pouvoir vérifier l'existence d'un fichier. Soit le problème sera permission deniedou no such file or directory. Si vous attrapez un IOError, définissez le IOError as e(comme ma première option), puis saisissez-le print(e.args)afin que vous puissiez, espérons-le, déterminer votre problème. J'espère que ça aide! :)

Zizouz212
la source
51

Date: 2017-12-04

Chaque solution possible a été répertoriée dans d'autres réponses.

Un moyen intuitif et discutable de vérifier si un fichier existe est le suivant:

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

J'ai fait une feuille de triche exhaustive pour votre référence:

#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']}
Calcul
la source
37

Si le fichier est destiné à être ouvert, vous pouvez utiliser l'une des techniques suivantes:

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

MISE À JOUR

Juste pour éviter toute confusion et sur la base des réponses que j'ai obtenues, la réponse actuelle trouve soit un fichier soit un répertoire avec le nom donné.

bergercookie
la source
9
Cette réponse est fausse. os.path.existsrenvoie true pour les éléments qui ne sont pas des fichiers, tels que les répertoires. Cela donne des faux positifs. Voir les autres réponses qui recommandent os.path.isfile.
Chris Johnson
a également eu le problème des faux positifs.
Zorglub29
docs.python.org/3/library/os.path.html#os.path.exists À l'instruction ci-dessus de chris >> os.path.exists (path)> Retourne True si path fait référence à un chemin existant ou à un open descripteur de fichier. Renvoie False pour les liens symboliques rompus. Sur certaines plates-formes, cette fonction peut retourner False si l'autorisation n'est pas accordée pour exécuter os.stat () sur le fichier demandé, même si le chemin existe physiquement. Modifié dans la version 3.3: le chemin peut maintenant être un entier: True est retourné s'il s'agit d'un descripteur de fichier ouvert, False sinon. Modifié dans la version 3.6: accepte un objet semblable à un chemin.
JayRizzo
36

Aditionellement, os.access() :

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

Être R_OK, W_OKet X_OKles drapeaux pour tester les autorisations ( doc ).

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

La levée d'exceptions est considérée comme une approche acceptable et Pythonique pour le contrôle de flux dans votre programme. Pensez à gérer les fichiers manquants avec IOErrors. Dans cette situation, une exception IOError sera déclenchée si le fichier existe mais que l'utilisateur ne dispose pas des autorisations de lecture.

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

CONvid19
la source
3
Le PO a demandé comment vérifier si un fichier existe. Il est possible qu'un fichier existe mais que vous ne puissiez pas l'ouvrir. Par conséquent, l'utilisation de l'ouverture d'un fichier comme proxy pour vérifier si le fichier existe n'est pas correcte: cela aura de faux négatifs.
Chris Johnson
19

Si vous avez importé NumPy déjà à d' autres fins alors il n'y a pas besoin d'importer d' autres bibliothèques comme pathlib, os, paths, etc.

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

Cela retournera vrai ou faux en fonction de son existence.

durjoy
la source
18

Vous pouvez écrire la suggestion de Brian sans le try:.

from contextlib import suppress

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

suppressfait partie de Python 3.4. Dans les versions plus anciennes, vous pouvez rapidement écrire votre propre suppression:

from contextlib import contextmanager

@contextmanager
def suppress(*exceptions):
    try:
        yield
    except exceptions:
        pass
Chris
la source
17

Je suis l'auteur d'un paquet qui existe depuis environ 10 ans, et il a une fonction qui répond directement à cette question. Fondamentalement, si vous êtes sur un système non Windows, il utilise Popenpour y accéder find. Cependant, si vous êtes sous Windows, il se réplique findavec un marcheur de système de fichiers efficace.

Le code lui-même n'utilise pas de trybloc… sauf pour déterminer le système d'exploitation et ainsi vous diriger vers le style "Unix" findou le hand-buillt find. Les tests de synchronisation ont montré qu'il tryétait plus rapide de déterminer le système d'exploitation, donc j'en ai utilisé un là-bas (mais nulle part ailleurs).

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

Et le doc…

>>> print pox.find.__doc__
find(patterns[,root,recurse,type]); Get path to a file or directory

    patterns: name or partial name string of items to search for
    root: path string of top-level directory to search
    recurse: if True, recurse down from root directory
    type: item filter; one of {None, file, dir, link, socket, block, char}
    verbose: if True, be a little verbose about the search

    On some OS, recursion can be specified by recursion depth (an integer).
    patterns can be specified with basic pattern matching. Additionally,
    multiple patterns can be specified by splitting patterns with a ';'
    For example:
        >>> find('pox*', root='..')
        ['/Users/foo/pox/pox', '/Users/foo/pox/scripts/pox_launcher.py']

        >>> find('*shutils*;*init*')
        ['/Users/foo/pox/pox/shutils.py', '/Users/foo/pox/pox/__init__.py']

>>>

L'implémentation, si vous voulez regarder, est ici: https://github.com/uqfoundation/pox/blob/89f90fb308f285ca7a62eabe2c38acb87e89dad9/pox/shutils.py#L190

Mike McKerns
la source
17

Vérifier que le fichier ou le répertoire existe

Vous pouvez suivre ces trois façons:

Remarque 1: os.path.isfileutilisé uniquement pour les fichiers

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

Remarque 2: os.path.existsutilisé pour les fichiers et les répertoires

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

La pathlib.Pathméthode (incluse dans Python 3+, installable avec pip pour Python 2)

from pathlib import Path
Path(filename).exists()
Ali Hallaji
la source
16

Ajout d'une autre légère variation qui ne se reflète pas exactement dans les autres réponses.

Cela gérera le cas de l' file_pathêtre Noneou de la chaîne vide.

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

Ajout d'une variante basée sur une suggestion de Shahbaz

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

Ajout d'une variante basée sur une suggestion de Peter Wood

def file_exists(file_path):
    return file_path and os.path.isfile(file_path):
Marcel Wilson
la source
3
if (x) return true; else return false;est vraiment juste return x. Vos quatre dernières lignes peuvent devenir return os.path.isfile(file_path). Pendant que nous y sommes, la fonction entière peut être simplifiée comme return file_path and os.path.isfile(file_path).
Shahbaz
Vous devez être prudent return xdans le cas de if (x). Python considérera une chaîne vide comme Faux, auquel cas nous retournerions une chaîne vide au lieu d'un booléen. Le but de cette fonction est de toujours renvoyer bool.
Marcel Wilson
1
Vrai. Dans ce cas cependant, xc'est os.path.isfile(..)donc déjà booléen.
Shahbaz
os.path.isfile(None)soulève une exception, c'est pourquoi j'ai ajouté le chèque if. Je pourrais probablement l'envelopper dans un essai / sauf à la place, mais je pensais que c'était plus explicite de cette façon.
Marcel Wilson
3
return file_path and os.path.isfile(file_path)
Peter Wood
15

Voici une commande Python 1 ligne pour l'environnement de ligne de commande Linux. Je trouve cela TRÈS PRATIQUE car je ne suis pas un gars Bash si chaud.

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

J'espère que ceci est utile.

Amour et paix - Joe Codeswell
la source
6
Vérification d'une ligne dans bash: [ -f "${file}" ] && echo "file found" || echo "file not found"(qui est identique à if [ ... ]; then ...; else ...; fi).
flotzilla
12

Vous pouvez utiliser la bibliothèque "OS" de Python:

>>> import os
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.txt") 
True
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.tx")
False
Pradip Das
la source
5
Cette réponse est fausse. os.path.existsrenvoie true pour les éléments qui ne sont pas des fichiers, tels que les répertoires. Cela donne des faux positifs. Voir les autres réponses qui recommandent os.path.isfile.
Chris Johnson
@Chris Johnson, la fonction os.path.exists () vérifie si un chemin existe dans le système. PATH peut être un RÉPERTOIRE ou un FICHIER. Cela fonctionnera bien sur les deux cas. Veuillez essayer avec un exemple
Pradip Das
Donc, cette réponse fonctionne. Génial. Si le chemin n'est pas celui d'un fichier. Est-ce là la question? Non.
Debosmit Ray
Ça dépend. Si le but de déterminer l'existence d'un "fichier" est de savoir si le chemin existe déjà (et n'est donc pas un chemin où de nouvelles données peuvent être stockées sans supprimer d'autres informations), alors tout existsva bien. Si le but est de déterminer s'il est sûr d'ouvrir un fichier vraisemblablement existant, alors la critique est justifiée et existe n'est pas assez précise. Malheureusement, l'OP ne précise pas quel est l'objectif souhaité (et ne le fera probablement plus).
starturtle
12

Comment vérifier si un fichier existe, sans utiliser l'instruction try?

En 2016, c'est sans doute la façon la plus simple de vérifier si un fichier existe et s'il s'agit d'un fichier:

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

isfileest en fait juste une méthode d'aide qui utilise en interne os.statet en stat.S_ISREG(mode)dessous. Il os.stats'agit d'une méthode de niveau inférieur qui vous fournira des informations détaillées sur les fichiers, les répertoires, les sockets, les tampons, etc. En savoir plus sur os.stat ici

Remarque: Cependant, cette approche ne verrouillera pas le fichier en aucune façon et donc votre code peut devenir vulnérable au " moment de la vérification au moment de l'utilisation " ( TOCTTOU bogues ).

Donc, lever des exceptions est considéré comme une approche acceptable et Pythonique pour le contrôle de flux dans votre programme. Et on devrait envisager de gérer les fichiers manquants avec IOErrors, plutôt que des ifinstructions ( juste un conseil ).

Inconnu
la source
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)
Khaled.K
la source
@ j6m8 yes, isReadableFile(path,fileName)retournera Truesi le fichier est accessible et lisible par le processus \ program \ thread
Khaled.K