web-dev-qa-db-fra.com

Meilleures pratiques pour les exceptions Python?

Quelles sont les meilleures pratiques pour créer des exceptions? Je viens de voir cela, et je ne sais pas si je devrais être horrifié, ou aimer. J'ai lu à plusieurs reprises dans des livres que les exceptions ne devraient jamais contenir de chaîne, car les chaînes elles-mêmes peuvent générer des exceptions. Une vraie vérité à cela?

D'après ce que j'ai compris des scripts, c'est ce qui a été fait afin que toutes les bibliothèques internes aient un format de message d'erreur commun (ce dont nous avons désespérément besoin), ce qui me permet de comprendre pourquoi la chaîne de message d'erreur est une bonne idée. (Presque toutes les méthodes jettent des exceptions en raison du besoin absolu de passer par rien d'invalide).

Le code en question est le suivant:

"""
Base Exception, Error
"""
class Error(Exception):
    def __init__(self, message):
        self.message = message

    def __str__(self):
        return "[ERROR] %s\n" % str(self.message)

    def log(self):
        ret = "%s" % str(self.message)
        if(hasattr(self, "reason")):
            return "".join([ret, "\n==> %s" % str(self.reason)])
        return ret

class PCSException(Error):
    def __init__(self, message, reason = None):
        self.message = message
        self.reason = reason
    def __str__(self):
        ret = "[PCS_ERROR] %s\n" % str(self.message)
        if(self.reason != None):
            ret += "[REASON] %s\n" % str(self.reason)
        return ret

Ce n'est que la partie visible de l'iceberg, mais quelqu'un peut-il m'expliquer en quoi cette idée est terrible? Ou si le processus/style de codage des exceptions est bien meilleur.

57
UberJumper

J'ai lu plusieurs fois dans des livres que les exceptions ne doivent jamais contenir un chaîne, car les chaînes elles-mêmes peuvent jeter des exceptions. Toute vérité à ce?

Quoi?

Veuillez fournir une référence ou un lien vers ceci. C'est totalement faux.

Étant donné que tous les objets peuvent générer des exceptions, aucun objet ne peut être contenu dans une exception par cette logique.

Non, le "no strings" est tout simplement fou dans un contexte Python. Peut-être que vous le lisez dans un contexte C++.


Modifier

Il était une fois (à l’époque ancienne) une exception Python pouvant être déclenchée par son nom plutôt que par la classe réelle.

raise "SomeNameOfAnExceptionClass"

C'est mauvais. Mais ceci est not incluant une chaîne dans une exception. Cela consiste à nommer l'exception avec une chaîne au lieu de l'objet de classe réel. Dans la version 2.5, cela peut toujours fonctionner, mais un avertissement de dépréciation est émis.

C’est peut-être ce que vous lisez "Ne pas déclencher d’exception avec un nom de chaîne"

32
S.Lott

Gestion des exceptions robuste (en Python) - un article de blog "Meilleures pratiques pour les exceptions Python" que j'ai écrit il y a longtemps. Vous pouvez peut-être le trouver utile.

Quelques points clés du blog:

N'utilisez jamais d'exceptions pour le contrôle de flux

Des exceptions existent pour les situations exceptionnelles: les événements qui ne sont pas un une partie de l'exécution normale.

Envisagez 'trouver' sur une chaîne renvoyant -1 si le motif n'est pas trouvé, mais l'indexation au-delà de la fin d'une chaîne déclenche une exception. Ne pas trouver la chaîne est une exécution normale.

Gère les exceptions au niveau qui sait comment les gérer

... 

Le Le meilleur endroit est ce morceau de code qui peut gérer l'exception. Pour certaines exceptions, telles que les erreurs de programmation (par exemple, IndexError, TypeError, NameError, etc.) sont mieux laissées au programmeur/utilisateur, parce que "les manipuler" ne fera que cacher de vrais bugs.

Demandez toujours "est-ce le bon endroit pour gérer cette exception?" et soyez prudent avec attraper toutes les exceptions.

Documentez les exceptions levées par votre code

...

penser aux exceptions que votre code peut créer vous aidera écrire du code meilleur, plus sûr et plus encapsulé

80
Eli Bendersky

Je crois que le conseil contre la création d'exceptions avec une chaîne provient de "Learning Python" (O'Reilly). Dans une section intitulée Les exceptions de chaînes sont correctes! , il indique la possibilité (maintenant supprimée) de créer une exception directement avec une chaîne arbitraire. 

Le code donné à titre d'exemple est:

myexc = "My exception string"
try:
    raise myexc
except myexc:
    print ('caught')

Ceci est sur p858 de la quatrième édition (livre de poche).

5
Graham Borland

La première impression est que c'est totalement trop de code pour une exception.

Les exceptions de formatage doivent être effectuées dans la configuration du consignateur. Même chose pour la journalisation elle-même.

Il redéfinit également l'attribut de message standard (et obsolète) et n'appelle pas le constructeur de la superclasse. (Cela pourrait ou non rompre le chaînage des exceptions Python 3.0, je n'ai pas essayé car j'exécute la version 2.6)

La plupart des actions du code supplémentaire peuvent être réalisées à l'aide de BaseException.args, en enregistrant ce qui suit sous le "message":

'\n==> '.join(exception.args)

Je dirais que si quelque chose peut être fait en utilisant un mécanisme commun/idiomatique, cela devrait être particulièrement fait dans la gestion des exceptions. (Les exceptions étant un mécanisme permettant de signaler quelque chose entre couches d'application.)

Personnellement, j'essaie d'éviter tout ce qui dépasse 

class SomeException(Exception): pass

(Avertissement: réponse subjective, éventuellement par la nature de la question.)

4
millimoose
class Error(Exception):
    """Base class for other exceptions"""
    pass

class empty_string_error(Error):
    """Raised when the input value is too large"""
    pass
while(1):
    try:
        if("Your Condition"):
            raise empty_string_error
        else:
            print("OUTPUT")
    except empty_string_error:
        print("APT MESSAGE")
        print(" ")
    finally:
        pint("Mandatory code")
0
Abhishek Bakolia