Adding content to exception messages

Sorry if this message is not a direct reply to Ka-Ping Yee message on PEP344, I'm in vacation in China and there's a thing I must say that could make sense in PEP344. I do a lot of exception re-raising at work; I use that technique to add content to exception messages while keeping the original stack. I even created a reraise function that I use that way: try: parser.parseFile(file) exeption Exception, exception: reraise(exception, "Error at line %s in file %s" % (x,y)) (x,y) are details, but you get the idea. This very useful in many situations. In the example, it works when an error is happening in parsing a file including other files (like xml files with <xs:include>). That way you get the exact path of inclusion leading to the error. It is also useful when an error happen in very generic code and when traceback is not enough to know which element was causing the error. What I propose is that all exceptions objects have a standard way to add additional informations. Something like: try: foo() except Exception, exception: exception.add_info("some info") raise exception from (whatever the proposition is) You might ask, "why not just reraise a new exception?". It is more useful to reraise the same exception type, making it possible to use selective except clauses and (avoid problems with code using them like hasattr). I think what would be simpler is not affect __str__ representation and prepend to a list the additional infos inside the exception object, adding a function to get these infos. I don't mind how it would be done in fact, as long as the need is fulfilled. I won't be able to read my messages often for the next 10 days, but I hope others will see the point I try to bring;) Regards, Nicolas Discover Yahoo! Have fun online with music videos, cool games, IM and more. Check it out! http://discover.yahoo.com/online.html

Nicolas Fleury wrote:
I do a lot of exception re-raising at work; I use that technique to add content to exception messages while keeping the original stack. I even created a reraise function that I use that way:
try: parser.parseFile(file) exeption Exception, exception: reraise(exception, "Error at line %s in file %s" % (x,y))
(x,y) are details, but you get the idea.
With PEP 344, this could simply be: try: parser.parseFile(file) exeption Exception, exception: raise type(exception)("Error at line %s in file %s" % (x,y)) Introspectively, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.blogspot.com

On Thu, 19 May 2005, Nick Coghlan wrote:
With PEP 344, this could simply be:
try: parser.parseFile(file) exeption Exception, exception: raise type(exception)("Error at line %s in file %s" % (x,y))
Only if we also made all exceptions new-style classes. That's just a minor nit, though. The more important question to me is: Do you care about the difference between a secondary exception that was raised intentionally (as in your example) and a secondary exception due to a problem in exception handling? (For me, the answer is yes.) -- ?!ng

Nick Coghlan wrote:
With PEP 344, this could simply be:
try: parser.parseFile(file) exeption Exception, exception: raise type(exception)("Error at line %s in file %s" % (x,y))
Introspectively, Nick.
It doesn't work (unless I misundertand you). For example, the exceptions.UnicodeTranslateError constructor needs 4 arguments, not 1. That's the reason why I think a parallel mechanism is necessary to add additional information when it is necessary to keep the same exception type. I probably didn't explain myself well too. Suppose this very hacky implementation working with the statu quo: class ExceptionStr: def __init__(self, content): self.content = content self.infos = [] def addinfo(self, info): self.infos.insert(0, info) def __call__(self): return '\n'.join(self.infos + [self.content]) import sys def reraise(exception, info=None): strFunc = getattr(exception, "__str__", None) if not isinstance(strFunc, ExceptionStr): strFunc = ExceptionStr(str(exception)) exception.__str__ = strFunc if info: strFunc.addinfo(info) raise exception, None, sys.exc_info()[-1] The following code: try: try: raise Exception("hello") except Exception, exception: reraise(exception, "doing x") except Exception, exception: reraise(exception, "doing y") would produce something like: Traceback (most recent call last): File "somefile.py", line 7, in ? reraise(exception, "doing y") File "somefile.py", line 5, in ? reraise(exception, "doing x") File "somefile..py", line 3, in ? raise Exception("hello") Exception: doing y doing x hello (Note that having the lines 5 and 7 in the traceback is not wanted) What I propose is to instead have something like: try: try: raise Exception("hello") except Exception, exception: # have some way to reraise a copy of "exception" # or the same exception with additional info "doing x" # For example: exception.addinfo("doing x") raise exception from exception.__context__ except Exception, exception: # Idem with "doing y" And have as output: Traceback (most recent call last): File "somefile..py", line 3, in ? raise Exception("hello") Additional info: doing y doing x Exception: hello Regards, Nicolas
participants (3)
-
Ka-Ping Yee
-
Nick Coghlan
-
Nicolas Fleury