Réponses:
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 try
autour 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
True
si 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 pathlib
module propose une approche orientée objet (rétroportée pathlib2
en 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 Path
objet 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 try
bloc:
try:
my_abs_path = my_file.resolve(strict=True)
except FileNotFoundError:
# doesn't exist
else:
# exists
FileNotFoundError
été introduit dans Python 3. Si vous devez également prendre en charge Python 2.7 ainsi que Python 3, vous pouvez utiliser à la IOError
place (quelles FileNotFoundError
sous-classes) stackoverflow.com/a/21368457/1960959
open('file', 'r+')
) puis rechercher jusqu'à la fin.
Vous avez la os.path.exists
fonction:
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.
Contrairement isfile()
, exists()
reviendra True
pour 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
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")
os.access()
renvoie false.
import os
, vous n'en avez plus besoin import os.path
car il en fait déjà partie os
. Vous avez juste besoin d'importer os.path
si vous n'utilisez que des fonctions depuis os.path
et non de os
lui-même, pour importer une chose plus petite, mais comme vous utilisez os.access
et os.R_OK
, la deuxième importation n'est pas nécessaire.
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
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 :
Solutions possibles :
[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.lexists
des comportements légèrement différents)
os.path.exists(path)
Renvoie
True
si chemin fait référence à un chemin existant ou à un descripteur de fichier ouvert. RenvoieFalse
les liens symboliques rompus. Sur certaines plates-formes, cette fonction peut retournerFalse
si 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 ()
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
[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.isfile
comportement (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.
Fonctions de traversée du système de fichiers (et recherchez les éléments correspondants dans les résultats)
[Python 3]: os. listdir ( path = '.' ) (ou [Python 3]: os. scandir ( path = '.' ) sur Python v 3.5 +, backport: [PyPI]: scandir )
Sous le capot, les deux utilisent:
via [GitHub]: python / cpython - (maître) cpython / Modules / posixmodule.c
L'utilisation de scandir () au lieu de listdir () peut augmenter considérablement les performances du code qui nécessite également des informations sur le type ou l'attribut de fichier, car les objets os.DirEntry exposent ces informations si le système d'exploitation les fournit lors de l'analyse d'un répertoire. Toutes les méthodes os.DirEntry peuvent effectuer un appel système, mais is_dir () et is_file () nécessitent généralement un appel système uniquement pour les liens symboliques; os.DirEntry.stat () nécessite toujours un appel système sous Unix mais n'en requiert qu'un pour les liens symboliques sous Windows.
os.listdir
( os.scandir
si disponible)glob.glob
)
os.listdir
É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.
[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)
... 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 :
os.F_OK
dans l'appel, mais c'est juste pour plus de clarté (sa valeur est 0 )
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 .
__declspec(dllexport)
(pourquoi diable la personne ordinaire ferait ça?), le programme principal est chargeable mais quasiment inutilisableInstaller 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.
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 :
Note (s) finale (s) :
glob.iglob
(et glob.glob
aussi) 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 glob
mé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.isdir
ouos.path.lexists
(selon que le chemin se termine /
).
os.path.isdir
ou os.path.lexist
puisqu'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).
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")
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/except
bloc 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
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:
try...except
ne permet pas de résoudre ce problème de toute façon.
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.)
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 Path
objet avec le nom de fichier, et vérifiez la is_file
mé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 à isfile
partir du os.path
module:
>>> 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 try
partout dans son implémentation.
Parce que Python utilise try
partout, 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.
Disponible depuis Python 3.4, utilisez le nouvel Path
objet dans pathlib
. Notez que ce .exists
n'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, NamedTemporaryFile
supprime 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_file
utilise 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
On aime try
parce 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 try
déclaration en utilisant le suppress
gestionnaire de contexte.
suppress
Python 3.4 nous donne le suppress
gestionnaire de contexte (anciennement le ignore
gestionnaire 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 try
dé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 try
volonté 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
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()
etisfile()
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 OSError
puis 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.
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 KeyboardInterrupt
et SystemExit
!) De passer silencieusement, ce qui est un bon moyen de masquer les bogues.
Cela semble encourager les utilisateurs à adopter de mauvaises pratiques.
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 os
facilite 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
.
os.path.exists
renvoie 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
.
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:
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
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():
...
pathlib
est 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.
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.
os.path.exists
renvoie 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
.
filepath
avec le bon timing, et BAM , vous écrasez le fichier cible. Vous devriez le faire open(filepath, 'wx')
dans un try...except
bloc pour éviter le problème.
OSError
si 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. "
os.replace
effectue de manière portative le remplacement silencieux du fichier de destination (il est identique au os.rename
comportement 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.
rename
exemple: Cela devrait toujours être fait avec try
/ except
. os.rename
(ou os.replace
sur 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
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.
try
Bien que je recommande toujours d'utiliser les instructions try
et except
, voici quelques possibilités pour vous (mon préféré est d'utiliser os.access
):
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 try
instruction 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
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
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 denied
ou 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! :)
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']}
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é.
os.path.exists
renvoie 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
.
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.
Vous pouvez écrire la suggestion de Brian sans le try:
.
from contextlib import suppress
with suppress(IOError), open('filename'):
process()
suppress
fait 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
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 Popen
pour y accéder find
. Cependant, si vous êtes sous Windows, il se réplique find
avec un marcheur de système de fichiers efficace.
Le code lui-même n'utilise pas de try
bloc… sauf pour déterminer le système d'exploitation et ainsi vous diriger vers le style "Unix" find
ou 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
Vous pouvez suivre ces trois façons:
Remarque 1:
os.path.isfile
utilisé 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.exists
utilisé 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.Path
méthode (incluse dans Python 3+, installable avec pip pour Python 2)
from pathlib import Path
Path(filename).exists()
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 None
ou 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):
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)
.
return x
dans 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.
x
c'est os.path.isfile(..)
donc déjà booléen.
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.
return file_path and os.path.isfile(file_path)
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.
[ -f "${file}" ] && echo "file found" || echo "file not found"
(qui est identique à if [ ... ]; then ...; else ...; fi
).
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
os.path.exists
renvoie 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
.
exists
va 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).
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
isfile
est en fait juste une méthode d'aide qui utilise en interne os.stat
et en stat.S_ISREG(mode)
dessous. Il os.stat
s'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 if
instructions ( juste un conseil ).
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)
isReadableFile(path,fileName)
retournera True
si le fichier est accessible et lisible par le processus \ program \ thread