Comment puis-je attraper une exception dans un décorateur, mais de permettre à l'appelant pour l'attraper?

J'ai une fonction python qui peut lever une exception. L'appelant intercepte l'exception et traite avec elle. Maintenant, je voudrais ajouter un décorateur à cette fonction que aussi intercepte l'exception, fait un peu de manipulation, mais puis re-soulève l'exception de permettre à l'appelant d'origine à gérer. Cela fonctionne, sauf que lorsque l'appelant d'origine affiche la pile d'appel de l'exception, il montre la ligne dans le décorateur, où il a été sur-relancé, pas là où elle s'est produite à l'origine. Exemple de code:

import sys,traceback

def mydec(func):
    def dec():
        try:
            func()
        except Exception,e:
            print 'Decorator handled exception %s' % e
            raise e
    return dec

@mydec
def myfunc():
    x = 1/0

try:
    myfunc()
except Exception,e:
    print 'Exception: %s' % e
    type,value,tb = sys.exc_info()
    traceback.print_tb(tb)

La sortie est:

Decorator handled exception integer division or modulo by zero
Exception: integer division or modulo by zero
  File "allbug.py", line 20, in <module>
    myfunc()
  File "allbug.py", line 9, in dec
    raise e

Je voudrais le décorateur à être en mesure de gérer l'exception, mais le traceback doit indiquer le x = 1/0 ligne plutôt que la raise ligne. Comment puis-je faire cela?

OriginalL'auteur Graeme Perrow | 2010-11-22