238 votes

Ajout d'informations à un python exception

EDIT: je suis en cours d'exécution python 2.6

Je veux arriver à quelque chose comme ceci

def foo():
   try:
       raise IOError('Stuff ')
   except:
       raise


def bar(arg1):
    try:
       foo()
    except Exception as e:
       e.message = e.message + 'happens at %s'%arg1
       raise

bar('arg1')
Traceback... 
IOError('Stuff Happens at arg1')

mais ce que je reçois est

Traceback.. 
IOError('Stuff')

Des indices quant à la façon de réaliser cet objectif?

Merci

158voto

martineau Points 21665

Je ferais comme cela, afin de changer son type en foo() ne nécessitent aussi l'évolution en bar().

def foo():
   try:
       raise IOError('Stuff')
   except:
       raise

def bar(arg1):
    try:
       foo()
    except Exception as e:
       raise type(e)(e.message + ' happens at %s' % arg1)

bar('arg1')
Traceback (most recent call last):
  File "test.py", line 13, in <module>
    bar('arg1')
  File "test.py", line 11, in bar
    raise type(e)(e.message + ' happens at %s' % arg1)
IOError: Stuff happens at arg1

Mise à jour

Voici une légère modification qui conserve l'original de l'exī:

...
def bar(arg1):
    try:
       foo()
    except Exception as e:
        import sys
        raise type(e), type(e)(e.message + 
                               ' happens at %s' % arg1), sys.exc_info()[2]

bar('arg1')
Traceback (most recent call last):
  File "test.py", line 16, in <module>
    bar('arg1')
  File "test.py", line 11, in bar
    foo()
  File "test.py", line 5, in foo
    raise IOError('Stuff')
IOError: Stuff happens at arg1

Mise à jour 2

Pour Python 3.x, le code dans ma première mise à jour est syntaxiquement incorrecte, plus l'idée d'avoir unmessage attributBaseExceptiona été rétractée dans un changement de PEP 352 sur 2012-05-16 (la mise à jour a été posté sur 2012-03-12). Alors, actuellement en Python 3.4.0 de toute façon, vous auriez besoin de faire quelque chose le long de ces lignes de préserver la traçabilité en amont et de ne pas coder en dur le type d'exception dans la fonctionbar():

# for Python 3.0+
...
def bar(arg1):
    try:
       foo()
    except Exception as e:
        import sys
        raise type(e)(str(e) +
                      ' happens at %s' % arg1).with_traceback(sys.exc_info()[2])

bar('arg1')

41voto

Steve Howard Points 2944

En supposant que vous ne voulez pas ou ne pouvez pas modifier foo(), vous pouvez essayer ceci:

try:
    raise IOError('stuff')
except Exception as e:
    e.args = (e.args[0] + ' happens',)
    raise

8voto

Kee Points 458

D'un seul coup d'approche que j'ai utilisé est de l'utilisation de l'attribut de classe comme espace de stockage pour plus de détails, comme un attribut de classe est accessible à la fois de la classe d'objet et de classe de l'instance:

class CustomError(Exception):
    details = None

Puis dans votre code:

exc = CustomError('Some message')
exc.details('Details -- add whatever you want')
raise exc

Et lors de la capture de l'erreur:

except CustomError, e:
    # Do whatever you want with the exception instance
    print e
    print e.details

2voto

bukzor Points 11085

À la différence des précédentes réponses, cela fonctionne dans le visage d'exceptions avec vraiment mauvais __str__. Il ne vous modifiez le type toutefois, afin de factoriser inutiles __str__ des implémentations.

Je voudrais encore à trouver une amélioration supplémentaire qui ne modifie pas le type.

from contextlib import contextmanager
@contextmanager
def helpful_info():
    try:
        yield
    except Exception as e:
        class CloneException(Exception): pass
        CloneException.__name__ = type(e).__name__
        CloneException.__module___ = type(e).__module__
        helpful_message = '%s\n\nhelpful info!' % e
        import sys
        raise CloneException, helpful_message, sys.exc_traceback


class BadException(Exception):
    def __str__(self):
        return 'wat.'

with helpful_info():
    raise BadException('fooooo')

L'original assurer la traçabilité et le type de (nom) sont préservés.

Traceback (most recent call last):
  File "re_raise.py", line 20, in <module>
    raise BadException('fooooo')
  File "/usr/lib64/python2.6/contextlib.py", line 34, in __exit__
    self.gen.throw(type, value, traceback)
  File "re_raise.py", line 5, in helpful_info
    yield
  File "re_raise.py", line 20, in <module>
    raise BadException('fooooo')
__main__.BadException: wat.

helpful info!

2voto

Alexander Kiselev Points 163

Vous pouvez définir votre propre exception qui hérite d'une autre et de créer son propre constructeur pour définir la valeur.

Par exemple:

class MyError(Exception):
   def __init__(self, value):
     self.value = value
     Exception.__init__(self)

   def __str__(self):
     return repr(self.value)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X