Question Comment ignorer correctement les exceptions


Lorsque vous voulez juste faire un essai - 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

607
2018-04-08 16:23


origine


Réponses:


try:
  doSomething()
except: 
  pass

ou

try:
  doSomething()
except Exception: 
  pass

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


845
2018-04-08 16:25



Il est généralement considéré comme une bonne pratique de ne détecter que les erreurs qui vous intéressent. Dans le cas de shutil.rmtree c'est probablement OSError:

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

Si vous voulez ignorer silencieusement cette erreur, vous feriez:

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

Pourquoi? Supposons que vous passiez accidentellement la fonction un nombre entier au lieu d'une chaîne, comme:

shutil.rmtree(2)

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

Si vous absolument vouloir ignorer toutes les erreurs, attraper Exception plutôt qu'un nu except: déclaration. Encore une fois, pourquoi?

Ne pas spécifier de captures d'exception chaque exception, y compris SystemExit exception qui, par exemple sys.exit() les usages:

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

Comparez ceci à ce qui suit, qui se termine correctement:

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

Si vous voulez écrire un code de comportement toujours meilleur, le OSError exception peut représenter diverses erreurs, mais dans l'exemple ci-dessus, nous voulons seulement ignorer Errno 2, donc nous pourrions être encore plus précis:

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 pourriez aussi import errno et changez le if à if e.errno == errno.ENOENT:


117
2018-04-09 21:48



Lorsque vous voulez juste faire un essai sans manipuler 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 arrêter l'exception de monter la pile, alors vous voulez quelque chose comme ceci:

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

106
2018-04-08 16:32



D'abord, je cite la réponse de Jack o'Connor de ce fil. Le thread référencé s'est fermé alors j'écris ici:

"Il y a une nouvelle façon de faire cela dans 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, qui parle de ça et de toutes sortes d'autres pythies hotness: https://youtu.be/OSGv2VnC0go?t=43m23s

Mon ajout à cela est l'équivalent de 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

64
2017-09-07 20:55



Pour l'exhaustivité:

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

...du tutoriel python.

Notez également que vous pouvez capturer l'exception comme ceci:

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

54
2018-03-05 23:02



Comment ignorer correctement les exceptions?

Il y a plusieurs façons de le faire.

Cependant, le choix de l'exemple a 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

Faites ceci:

shutil.rmtree(path, ignore_errors=True)

Ceci est un argument spécifique à shutil.rmtree. Vous pouvez voir l'aide en faisant ce qui suit, et vous verrez qu'il peut également permettre des fonctionnalités sur les erreurs.

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

Puisque cela ne couvre que le cas étroit de l'exemple, je vais démontrer plus loin comment gérer cela si ces arguments de mot-clé 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 vais démontrer plus loin comment gérer cela si ces arguments de mot-clé n'existaient pas.

Nouveau dans Python 3.4:

Vous pouvez importer le suppress gestionnaire de contexte:

from contextlib import suppress

Mais seulement supprimer l'exception la plus spécifique:

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

Vous allez ignorer silencieusement un FileNotFoundError:

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

Du 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ù continuer silencieusement avec l'exécution du programme est connu pour être le   bonne chose à faire.

Notez que suppress et FileNotFoundError sont uniquement disponibles en Python 3.

Si vous voulez que votre code fonctionne également dans Python 2, consultez la section suivante:

Python 2 et 3:

Lorsque 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

Pour le code compatible Python 2, pass est la bonne façon d'avoir une déclaration qui est une no-op. Mais quand tu fais un nu except:, c'est la même chose que de faire except BaseException: qui comprend GeneratorExit, KeyboardInterrupt, et SystemExitet en général, vous ne voulez pas attraper ces choses.

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

Voici une partie du Python (2) hiérarchie d'exceptionComme vous pouvez le voir, si vous observez des exceptions plus générales, vous pouvez masquer les problèmes auxquels vous ne vous attendiez pas:

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 un OSError ici, et peut-être que l'exception dont vous n'avez pas besoin est s'il n'y a pas de répertoire.

On peut avoir cette numéro d'erreur spécifique de la errno bibliothèque, et sur-relance si nous ne l'avons pas:

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 

Notez, une augmentation nue soulève l'exception d'origine, ce qui est probablement ce que vous voulez dans ce cas. Écrit de façon plus concise, car nous n'avons pas vraiment besoin d'explicitement pass avec le 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
2018-01-22 04:42



@Quand vous voulez juste faire un essai sans manipuler l'exception, comment le faites-vous en Python?

Cela vous aidera à imprimer quelle exception est :( c'est-à-dire, essayez de récupérer sans gérer l'exception et imprimer l'exception.)

importer sys
....
essayer:
    faire quelque chose()
sauf:
    print "Erreur inattendue:", sys.exc_info () [0]

...

reg, Tilokchan


12
2017-10-12 05:36



try:
      doSomething()
except Exception: 
    pass
else:
      stuffDoneIf()
      TryClauseSucceeds()

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


8
2017-11-19 22:35



En Python, nous gérons des exceptions similaires à d'autres langages, mais la différence est une différence de syntaxe, par exemple,

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
2017-11-18 10:27



Simplement élever l'exception pertinente, juste comme ceci:

try:
     raise NameError('Joan')
 except NameError:
     print 'An exception just raised again by Joan!'
     raise

Aussi simple que cela. :)

Pour plus de détails, lisez cette documentation: https://docs.python.org/3.6/tutorial/errors.html


-1
2018-06-03 19:46



Gérer une exception en Python: Si vous avez un code suspect pouvant générer une exception, vous pouvez défendre votre programme en plaçant le code suspect dans un try: block.

try:
    # Your statements .............
except ExceptionI:
    # Your statements.............
except ExceptionII:
    # Your statements..............
else:
   # Your statements

-1
2017-08-03 05:33