web-dev-qa-db-fra.com

Comment ignorer correctement les exceptions

Quand vous voulez juste essayer - sauf sans gérer l'exception, comment le faites-vous en Python?

Est-ce que ce qui suit est la bonne façon de le faire?

try:
    shutil.rmtree(path)
except:
    pass
650
Joan Venge
try:
  doSomething()
except: 
  pass

ou

try:
  doSomething()
except Exception: 
  pass

La différence est que le premier va aussi attraper KeyboardInterrupt, SystemExit et des trucs comme ça, qui sont directement dérivés de exceptions.BaseException, pas exceptions.Exception.
Voir la documentation pour plus de détails:

904
vartec

Il est généralement considéré comme la meilleure pratique de ne capturer que les erreurs qui vous intéressent. Dans le cas de shutil.rmtree, il s'agit probablement de OSError:

>>> shutil.rmtree("/fake/dir")
Traceback (most recent call last):
    [...]
OSError: [Errno 2] No such file or directory: '/fake/dir'

Si vous voulez ignorer cette erreur en silence, vous feriez:

try:
    shutil.rmtree(path)
except OSError:
    pass

Pourquoi? Dites que vous (d'une manière ou d'une autre) passez accidentellement à la fonction un entier au lieu d'une chaîne, comme:

shutil.rmtree(2)

Cela donnera l'erreur "TypeError: contraindre à Unicode: chaîne nécessaire ou tampon, int trouvé" - vous ne voulez probablement pas l'ignorer, ce qui peut être difficile à déboguer.

Si vous décidément voulez ignorer toutes les erreurs, récupérez Exception plutôt qu'une instruction nue except:. Encore une fois, pourquoi?

Ne pas spécifier d'exception intercepte all exception, y compris l'exception SystemExit qui, par exemple, sys.exit() utilise:

>>> try:
...     sys.exit(1)
... except:
...     pass
... 
>>>

Comparez ceci à ce qui suit, qui existe correctement:

>>> try:
...     sys.exit(1)
... except Exception:
...     pass
... 
Shell:~$ 

Si vous voulez écrire du code toujours meilleur, le OSError exception peut représenter diverses erreurs, mais dans l'exemple ci-dessus, nous voulons seulement ignorer Errno 2.

try:
    shutil.rmtree(path)
except OSError, e:
    if e.errno == 2:
        # suppress "No such file or directory" error
        pass
    else:
        # reraise the exception, as it's an unexpected error
        raise

Vous pouvez également import errno et changer la if en if e.errno == errno.ENOENT:

124
dbr

Quand vous voulez juste essayer un catch sans gérer l'exception, comment le faites-vous en Python?

Cela dépend de ce que vous entendez par "manipulation".

Si vous voulez l'attraper sans prendre aucune mesure, le code que vous avez posté fonctionnera.

Si vous voulez dire que vous voulez agir sur une exception sans empêcher l’exception de remonter dans la pile, vous voulez quelque chose comme ceci:

try:
    do_something()
except:
    handle_exception()
    raise  #re-raise the exact same exception that was thrown
108
Jason Baker

Je cite d’abord la réponse de Jack O'Connor dans ce fil . Le fil de référence s'est fermé alors j'écris ici:

"Il existe une nouvelle façon de faire cela en Python 3.4:

from contextlib import suppress

with suppress(Exception):
    # your code

Voici le commit qui l'a ajouté: http://hg.python.org/cpython/rev/406b47c64480

Et voici l'auteur, Raymond Hettinger, parlant de cela et de toutes sortes d'autres actualités Python: https://youtu.be/OSGv2VnC0go?t=43m23s

Mon ajout à cela est l'équivalent Python 2.7:

from contextlib import contextmanager

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

Ensuite, vous l’utilisez comme dans Python 3.4:

with ignored(Exception):
    # your code
72
Jabba

Pour être complet:

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print "division by zero!"
...     else:
...         print "result is", result
...     finally:
...         print "executing finally clause"

... à partir du tutoriel python .

Notez également que vous pouvez capturer l'exception de la manière suivante:

>>> try:
...     this_fails()
... except ZeroDivisionError as detail:
...     print 'Handling run-time error:', detail
54
cbare

Comment ignorer correctement les exceptions?

Il y a plusieurs façons de le faire. 

Cependant, le choix de l'exemple offre une solution simple qui ne couvre pas le cas général.

Spécifique à l'exemple:

Au lieu de 

try:
    shutil.rmtree(path)
except:
    pass

Faire ceci:

shutil.rmtree(path, ignore_errors=True)

Ceci est un argument spécifique à shutil.rmtree. Vous pouvez voir l’aide à ce sujet en procédant comme suit et vous verrez également qu’elle peut également permettre une fonctionnalité sur les erreurs.

>>> import shutil
>>> help(shutil.rmtree)

Etant donné que cela ne couvre que le cas étroit de l'exemple, je montrerai plus loin comment gérer cela si ces arguments de mots clés n'existaient pas.

Approche générale

Étant donné que ce qui précède ne couvre que le cas étroit de l'exemple, je montrerai plus loin comment gérer cela si ces arguments de mots clés n'existaient pas.

Nouveau dans Python 3.4:

Vous pouvez importer le gestionnaire de contexte suppress:

from contextlib import suppress

Mais ne supprimez que l'exception la plus spécifique:

with suppress(FileNotFoundError):
    shutil.rmtree(path)

Vous allez ignorer silencieusement une FileNotFoundError:

>>> with suppress(FileNotFoundError):
...     shutil.rmtree('bajkjbkdlsjfljsf')
... 
>>> 

De la docs :

Comme avec tout autre mécanisme qui supprime complètement les exceptions, Ce gestionnaire de contexte ne doit être utilisé que pour couvrir des erreurs très spécifiques où l’exécution silencieuse du programme est connue pour être le bonne chose à faire.

Notez que suppress et FileNotFoundError ne sont disponibles que dans Python 3.

Si vous souhaitez que votre code fonctionne également dans Python 2, reportez-vous à la section suivante:

Python 2 et 3:

Quand vous voulez juste essayer/sauf sans gérer l'exception, comment faites-vous en Python?

Est-ce que la suite est la bonne façon de le faire?

try :
    shutil.rmtree ( path )
except :
    pass

Pour le code compatible Python 2, pass est la méthode correcte pour obtenir une instruction non-op. Mais quand vous faites un except: nu, cela revient à faire except BaseException: qui inclut GeneratorExit, KeyboardInterrupt et SystemExit, et en général, vous ne voulez pas intercepter ces choses. 

En fait, vous devriez être aussi précis que possible en nommant l'exception. 

Voici une partie de Python (2) hiérarchie des exceptions , et comme vous pouvez le constater, si vous détectez des exceptions plus générales, vous pouvez masquer des problèmes inattendus:

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StandardError
      |    +-- BufferError
      |    +-- ArithmeticError
      |    |    +-- FloatingPointError
      |    |    +-- OverflowError
      |    |    +-- ZeroDivisionError
      |    +-- AssertionError
      |    +-- AttributeError
      |    +-- EnvironmentError
      |    |    +-- IOError
      |    |    +-- OSError
      |    |         +-- WindowsError (Windows)
      |    |         +-- VMSError (VMS)
      |    +-- EOFError
... and so on

Vous voulez probablement attraper une erreur OSE ici, et peut-être que l'exception qui vous importe le moins est peut-être qu'il n'y a pas de répertoire. 

Nous pouvons obtenir ce numéro d'erreur spécifique de la bibliothèque errno et le rediffuser si nous n'avons pas cela:

import errno

try:
    shutil.rmtree(path)
except OSError as error:
    if error.errno == errno.ENOENT: # no such file or directory
        pass
    else: # we had an OSError we didn't expect, so reraise it
        raise 

Remarque, une augmentation nue soulève l'exception d'origine, ce qui est probablement ce que vous voulez dans ce cas. Écrit de manière plus concise, car nous n'avons pas vraiment besoin de pass explicitement avec du code dans la gestion des exceptions:

try:
    shutil.rmtree(path)
except OSError as error:
    if error.errno != errno.ENOENT: # no such file or directory
        raise 
40
Aaron Hall

Lorsque vous voulez juste essayer un catch sans gérer l'exception, comment faites-vous en Python?

Cela vous aidera à imprimer ce qu'est l'exception :( c'est-à-dire essayez catch sans gérer l'exception et imprimez l'exception.)

import sys
try:
    doSomething()
except:
    print "Unexpected error:", sys.exc_info()[0]
12
try:
      doSomething()
except Exception: 
    pass
else:
      stuffDoneIf()
      TryClauseSucceeds()

Pour votre information, la clause else peut aller après toutes les exceptions et ne sera exécutée que si le code de l'essai ne provoque pas d'exception. 

9
MrChrisRodriguez

En Python, nous traitons des exceptions similaires à celles d’autres langages, mais la différence est une différence de syntaxe,

try:
    #Your code in which exception can occur
except <here we can put in a particular exception name>:
    # We can call that exception here also, like ZeroDivisionError()
    # now your code
# We can put in a finally block also
finally:
    # Your code...
3

J'avais besoin d'ignorer les erreurs dans plusieurs commandes et fuckit a fait le tour

import fuckit

@fuckit
def helper():
    print('before')
    1/0
    print('after1')
    1/0
    print('after2')

helper()
0
citynorman