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
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:
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:
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
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
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
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.
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.
É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.
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:
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
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]
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.
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...
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()