4
votes

Comment créer une exception python avec plusieurs causes?

Comment puis-je lever une exception python avec plusieurs causes, similaire à celle de Java fonctionnalité addSuppressed () ? Par exemple, j'ai une liste de plusieurs méthodes à essayer et si aucune d'entre elles ne fonctionne, je veux lever une exception qui inclut les exceptions de toutes les méthodes qui ont été essayées. C'est-à-dire :

exceptions = []
for method in methods_to_try:
  try:
    method()
  except Exception as e:
    exceptions.append(e)
if exceptions:
  raise Exception("All methods failed") from exceptions

Mais ce code échoue car l'instruction rise ... from ... attend une seule exception et non une liste. Les solutions Python 2 ou 3 sont acceptables. Toutes les traces de retour et tous les messages d'exception doivent être préservés.


1 commentaires

vous ne pouvez pas lever plusieurs exceptions. Créez une grande exception avec toutes les traces de pile et augmentez-la. Ça va être moche


3 Réponses :


0
votes

Utilisez plutôt la journalisation

Si l'utilisation du module de journalisation est acceptable pour vous, je suppose que ce serait le plus propre de consigner les exceptions individuelles que vous avez détectées et de ne lever qu'une seule exception globale.

Si vous souhaitez uniquement afficher les messages du journal en cas d'erreur de toutes les fonctions essayées, c'est un cas idéal pour le logger tamponné de journal de recettes de journalisation Vous pouvez le modifier pour toujours vous connecter au niveau de débogage, mais augmenter le niveau en erreur, si toutes les sous-fonctions génèrent une erreur.


1 commentaires

La journalisation crée des effets secondaires indésirables pour le code. Je recherche un moyen de conserver plusieurs exceptions / retraits dans une seule exception soulevée.



2
votes

Il suffit de transmettre les exceptions comme arguments lors de la création de la dernière exception.

for method in methods_to_try:
    try:
        method()
    except Exception as e:
        exceptions.append(e)
if exceptions:
    raise Exception(*exceptions)

Elles seront disponibles dans l'attribut args .


3 commentaires

Je ne vois toujours que le traçage de la dernière exception soulevée. Je recherche une solution qui préserve tous les retraits.


@Evan Les traces sont à l'intérieur des exceptions, si vous voulez les imprimer, vous devez écrire le code. AFAIK la gestion python par défaut ne peut pas faire ce que vous voulez. Consultez le module traceback pour obtenir de l'aide.


Seules les exceptions python 3 ont __traceback__ . Sur python 2, vous pouvez utiliser sys.exc_info pour stocker le traçage avant d'ajouter l'exception.



1
votes

Une fois pourrait lever chaque exception de l'autre pour l'enchaîner. Le seul problème concerne l'ordre de cause qui peut être trompeur.

def combine_exc(exceptions):
   c_exc = None
   for ex in reversed(exceptions):
      try:
         if c_exc is None:
            raise ex
         else:
            raise ex from c_exc
      except Exception as ex1:
         c_exc = ex1

   return c_exc


0 commentaires