web-dev-qa-db-fra.com

Comment empêcher "une exception trop large" dans ce cas?

J'ai une liste de fonctions qui peuvent échouer, et si une échoue, je ne veux pas que le script s'arrête, mais continue avec la fonction suivante.

Je l'exécute avec quelque chose comme ça:

list_of_functions = [f_a,f_b,f_c]
for current_function in list_of_functions:
    try:
        current_function()
    except Exception:
        print(traceback.format_exc())

Cela fonctionne bien, mais il n'est pas conforme à PEP8:

Lorsque vous interceptez des exceptions, mentionnez des exceptions spécifiques chaque fois que possible au lieu d'utiliser une simple exception: clause.

Par exemple, utilisez:

try:
    import platform_specific_module
except ImportError:
    platform_specific_module = None

Une clause bare except: attrapera SystemExit et KeyboardInterrupt exceptions, ce qui rend plus difficile d'interrompre un programme avec Control-C, et peut dissimuler d’autres problèmes. Si vous voulez intercepter toutes les exceptions cette erreur de programme signal, utilisez sauf Exception: (nu sauf est équivalent à sauf BaseException:).

Une bonne règle est de limiter l’utilisation des clauses nues «sauf» à deux cas:

Si le gestionnaire d'exceptions doit imprimer ou consigner la trace; au moins, l'utilisateur sera informé qu'une erreur est survenue.

Si le code doit effectuer un travail de nettoyage, laissez ensuite l'exception se propager vers le haut avec une levée. essayez ... enfin peut être un meilleur façon de gérer cette affaire.

Comment est-ce la bonne façon?

15
Blusky

Le guide PEP8 que vous citez suggère qu'il est correct d'utiliser une seule exception à votre cas, à condition que vous enregistriez les erreurs. Je pense que vous devriez couvrir autant d’exceptions que vous pouvez/savoir comment gérer puis consigner le reste et pass, par exemple.

import logging

list_of_functions = [f_a,f_b,f_c]
for current_function in list_of_functions:
    try:
        current_function()
    except KnownException:
        raise
    except Exception as e:
        logging.exception(e)
21
Ed Smith

//youtrack.jetbrains.com/issue/PY-9715

PY-9715 Inspection incohérente "Clauses d'exception trop larges" [Inspection "Clauses d'exception trop larges"] [1]

//legacy.python.org/dev/peps/pep-0348/

BaseException

La super-classe dont toutes les exceptions doivent hériter. Son nom était choisi pour refléter le fait qu’il est à la base de la hiérarchie des exceptions tout en étant une exception elle-même. "Raisable" était considéré comme un nom, il a été transmis parce que son nom ne reflétait pas correctement le fait que c'est une exception elle-même.

L'héritage direct de BaseException n'est pas prévu et sera découragé pour le cas général. La plupart des exceptions définies par l'utilisateur devraient hériter d'Exception à la place. Cela permet de capturer Exception à continuer à travailler dans le cas habituel de la capture de toutes les exceptions qui devrait être attrapé. L'héritage direct de BaseException ne devrait être que fait dans les cas où une toute nouvelle catégorie d’exceptions est souhaitée.

Mais, pour les cas où toutes les exceptions devraient être capturées aveuglément, à l'exception de BaseException fonctionnera.

[1] http://i.stack.imgur.com/8UByz.png

//youtrack.jetbrains.com/issue/PY-9715

//legacy.python.org/dev/peps/pep-0348/

0
xgqfrms

Voulez-vous dire peut-être que chaque fonction peut générer différentes exceptions? Lorsque vous nommez le type d'exception dans la clause except, il peut s'agir de tout nom faisant référence à une exception, et pas uniquement du nom de la classe.

par exemple.

def raise_value_error():
    raise ValueError

def raise_type_error():
    raise TypeError

def raise_index_error():
    doesnt_exist

func_and_exceptions = [(raise_value_error, ValueError), (raise_type_error, TypeError), 
    (raise_index_error, IndexError)]

for function, possible_exception in func_and_exceptions:
   try:
       function()
   except possible_exception as e:
       print("caught", repr(e), "when calling", function.__name__)

impressions:

caught ValueError() when calling raise_value_error
caught TypeError() when calling raise_type_error
Traceback (most recent call last):
  File "run.py", line 14, in <module>
    function()
  File "run.py", line 8, in raise_index_error
    doesnt_exist
NameError: name 'doesnt_exist' is not defined

Bien entendu, vous ne savez plus quoi faire à chaque exception. Mais puisque vous voulez juste l'ignorer et continuer, alors ce n'est pas un problème.

0
Dunes