Comment ignorer correctement les exceptions
-
06-09-2019 - |
Question
Si vous voulez juste faire un essai, sauf sans manipuler l'exception, comment voulez-vous le faire en Python?
est-ce qui suit la bonne façon de le faire?
try:
shutil.rmtree(path)
except:
pass
La solution
try:
doSomething()
except:
pass
ou
try:
doSomething()
except Exception:
pass
La différence est que le premier va également prendre KeyboardInterrupt
, SystemExit
et des trucs comme ça, qui sont dérivés directement de exceptions.BaseException
, non exceptions.Exception
Voir la documentation pour plus de détails:.
-
instruction try
- - http://docs.python.org/reference/compound_stmts.html #try
- exceptions - http://docs.python.org/library/exceptions
Autres conseils
Il est généralement considéré comme la meilleure pratique pour n'attraper les erreurs qui vous intéressent Dans le cas de shutil.rmtree
il 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 (en quelque sorte) passe par mégarde la fonction d'un nombre entier au lieu d'une chaîne, comme:
shutil.rmtree(2)
Il donnera l'erreur « TypeError: contraindre à Unicode: chaîne de besoin ou d'un tampon, int trouvé » - vous ne voulez probablement pas ignorer que, ce qui peut être difficile à déboguer
Si vous définitivement voulez ignorer toutes les erreurs, Exception
de capture plutôt que d'une déclaration de except:
nue. Encore une fois, pourquoi?
Non spécifiant une capture d'exception tous exception, y compris l'exception de SystemExit
qui, par exemple sys.exit()
utilise:
>>> try:
... sys.exit(1)
... except:
... pass
...
>>>
Comparez cela à ce qui suit, qui sort correctement:
>>> try:
... sys.exit(1)
... except Exception:
... pass
...
shell:~$
Si vous voulez écrire un code toujours mieux se comporter, OSError
exception peut représenter diverses erreurs, mais dans l'exemple ci-dessus nous ne voulons ignorer Errno 2
, afin que nous puissions ê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 pouvez également import errno
et changer le if
à if e.errno == errno.ENOENT:
Si vous voulez juste faire une capture d'essai sans avoir à manipuler l'exception, comment voulez-vous le faire en Python?
Cela dépend de ce que vous entendez par « la manipulation ».
Si vous voulez parler de l'attraper sans prendre aucune mesure, le code affiché fonctionnera.
Si vous voulez dire que vous voulez prendre des mesures à une exception sans arrêter l'exception d'aller la pile, vous voulez quelque chose comme ceci:
try:
do_something()
except:
handle_exception()
raise #re-raise the exact same exception that was thrown
Tout d'abord je cite la réponse de Jack o'Connor de ce fil . Le fil référencé a été fermé, donc j'écris ici:
"Il y a une nouvelle façon de le faire venir en Python 3.4:
from contextlib import suppress
with suppress(Exception):
# your code
Voici le commit qui a ajouté qu'il: http://hg.python.org/cpython/rev / 406b47c64480
Et voici l'auteur, Raymond Hettinger, en parlant de cela et toutes sortes d'autres Python Hotness: https: / /youtu.be/OSGv2VnC0go?t=43m23s
Mon plus de 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 en Python 3.4:
with ignored(Exception):
# your code
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 python tutoriel .
Notez également que vous pouvez capturer l'exception comme ceci:
>>> try:
... this_fails()
... except ZeroDivisionError as detail:
... print 'Handling run-time error:', detail
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écifiques à l'exemple:
Au lieu de
try:
shutil.rmtree(path)
except:
pass
Pour ce faire:
shutil.rmtree(path, ignore_errors=True)
Ceci est un argument spécifique à shutil.rmtree
. Vous pouvez voir l'aide en procédant comme suit, et vous verrez peut également permettre la fonctionnalité sur les erreurs aussi bien.
>>> import shutil
>>> help(shutil.rmtree)
Étant donné que ce ne couvre que le cas étroit de l'exemple, je vais encore montrer comment gérer cela si ces arguments clés n'existaient pas.
Approche générale
Comme ci-dessus ne couvre que le cas étroit de l'exemple, je vais encore montrer comment gérer cela si ces arguments clés n'existaient pas.
Nouveau en Python 3.4:
Vous pouvez importer le gestionnaire de contexte suppress
:
from contextlib import suppress
Mais seulement supprimer l'exception plus spécifique:
with suppress(FileNotFoundError):
shutil.rmtree(path)
Vous silencieusement ignorer un FileNotFoundError
:
>>> with suppress(FileNotFoundError):
... shutil.rmtree('bajkjbkdlsjfljsf')
...
>>>
De la docs :
Comme tout autre mécanisme qui supprime complètement les exceptions, ce gestionnaire de contexte doit être utilisé que pour couvrir des erreurs très spécifiques où continue en silence avec l'exécution du programme est connu pour être le bonne chose à faire.
Notez que suppress
et FileNotFoundError
ne sont disponibles en Python 3.
Si vous voulez que votre code fonctionne en Python 2 ainsi, voir la section suivante:
Python 2 et 3:
Si vous voulez juste faire un essai / sauf sans gérer l'exception, comment voulez-vous le faire en Python?
est-ce qui suit la bonne façon de le faire?
try : shutil.rmtree ( path ) except : pass
Pour Python 2 code compatible, pass
est la bonne façon d'avoir une déclaration qui est un non-op. Mais quand vous faites un except:
nu, qui est la même chose que faire except BaseException:
qui comprend GeneratorExit
, KeyboardInterrupt
et SystemExit
, et en général, vous ne voulez pas attraper ces choses.
En fait, vous devriez être aussi précis en nommant l'exception que vous pouvez.
Voici une partie du Python (2) hiérarchie exception , et comme vous pouvez le voir, si vous attrapez des exceptions plus générales, vous pouvez cacher les problèmes que 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 l'exception que vous ne se soucient pas est de savoir s'il n'y a pas de répertoire.
Nous pouvons obtenir que numéro d'erreur spécifique de la bibliothèque errno
, et si nous ne reraise 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
Note, 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, comme on n'a pas vraiment besoin de pass
explicitement 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
Si vous voulez juste faire une capture d'essai sans avoir à manipuler l'exception, comment voulez-vous le faire en Python?
Cela vous aidera à imprimer ce que l'exception est :( dire essayer prise sans gérer l'exception et imprimer l'exception.)
import sys
try:
doSomething()
except:
print "Unexpected error:", sys.exc_info()[0]
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 dans l'essai ne provoque pas une exception.
En Python, nous traitons des exceptions semblables à une autre langue, 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...
Je avais besoin d'ignorer les erreurs dans plusieurs commandes et fuckit a fait l'affaire
import fuckit
@fuckit
def helper():
print('before')
1/0
print('after1')
1/0
print('after2')
helper()
Il suffit de augmenter l'exception pertinente, 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, ne lisez cette documentation: https://docs.python.org/3.6/tutorial/errors.html