web-dev-qa-db-fra.com

"Open ()" de Python génère différentes erreurs pour "fichier non trouvé" - comment gérer les deux exceptions?

J'ai un script où un utilisateur est invité à taper un nom de fichier (d'un fichier à ouvrir), et si le fichier n'existe pas dans le répertoire en cours, l'utilisateur est invité à nouveau. Voici la version courte:

file = input("Type filename: ")

...
try:
    fileContent = open(filename, "r")
    ...
except FileNotFoundError:
    ...

Lorsque j'ai testé mon script sur mon MacOS X dans Python 3.3x), il fonctionnait parfaitement bien lorsque je tapais exprès le nom de fichier incorrect (la suite est exécutée sous "expect").

Cependant, lorsque je voulais exécuter mon code sur un ordinateur Windows sous Python 3.2x, je reçois une erreur indiquant que "FileNotFoundError" n'est pas défini. Donc, Python 3.2 sur Windows pense que "FileNotFoundError" est une variable et que le programme se ferme avec une erreur.

J'ai découvert que Python 3.2 sous Windows génère un "IOError" si le nom du fichier en entrée n'est pas valide. Je l'ai testé sur ma machine Linux sous Python 2.7, et c'est aussi un IOError.

Mon problème est maintenant, que le code avec

except "FileNotFoundError":

ne fonctionnera pas sous Windows Python 3.2, mais si je le change en

except "IOError":

ça ne marchera plus sur mon Mac.

Comment pourrais-je le contourner? Le seul moyen auquel je puisse penser est d'utiliser uniquement except, ce que je ne veux généralement pas.

41
user2015601

En 3.3, IOError est devenu un alias pour OSError , et FileNotFoundError est une sous-classe de OSError. Alors tu pourrais essayer

except (OSError, IOError) as e:
   ...

Cela va jeter un filet assez large, et vous ne pouvez pas supposer que l’exception est "fichier non trouvé" sans inspecter e.errno, mais cela peut couvrir votre cas d'utilisation.

PEP 3151 explique en détail la raison du changement.

65
Russell Borogove

Cela me semble meilleur qu'un simple except:, mais je ne suis pas sûr que ce soit la meilleure solution:

error_to_catch = getattr(__builtins__,'FileNotFoundError', IOError)

try:
    f = open('.....')
except error_to_catch:
    print('!')
10
cwallenpoole

Donc, pour attraper exactement que lorsqu'un fichier n'est pas trouvé, je fais:

import errno
try:
   open(filename, 'r')
except (OSError, IOError) as e: # FileNotFoundError does not exist on Python < 3.3
   if getattr(e, 'errno', 0) == errno.ENOENT:
      ... # file not found
   raise
5
Alex Che

vous pouvez attraper 2 erreurs en même temps

except (FileNotFoundError, IOError):

Je n'avais pas réalisé que c'était ce que vous demandiez. J'espère qu'il existe une solution plus éloquente que d'inspecter manuellement

try:
   error_to_catch = FileNotFoundError
except NameError:
   error_to_catch = IOError

except error_to_catch

cwallenpoole fait cela plus éloquemment dans sa réponse (error_to_catch = getattr(__builtins__,'FileNotFoundError', IOError))

2
dm03514