3

Suppose I have the following:

def foo():
    bar()

def bar():
    baz()

def baz():
    raise ValueError("hello")

foo()

unsurprisingly, the trace is

$ python x.py
Traceback (most recent call last):
  File "x.py", line 10, in <module>
    foo()
  File "x.py", line 2, in foo
    bar()
  File "x.py", line 5, in bar
    baz()
  File "x.py", line 8, in baz
    raise ValueError("hello")
ValueError: hello

Now suppose I want the traceback to look like this

Traceback (most recent call last):
  File "x.py", line 10, in <module>
    foo()
ValueError: hello

That is, I want to be able to remove the topmost two entries in the stack trace, and I want to do it within baz(), that is, at the raising of the exception, either by mangling the stack, or by crafting the raised exception in a special way.

Is it possible?

Edit: one option would be to raise inside baz and catch immediately, then re-raise with a trimmed traceback, but I don't know how to do it.

Edit 2:

what I need is this, in pseudocode

def baz():
    raise ValueError, "hello", <traceback built from current frame stack, except the last two>
Stefano Borini
  • 138,652
  • 96
  • 297
  • 431
  • 1
    appears as a duplicate of http://stackoverflow.com/questions/2615414/python-eliminating-stack-traces-into-library-code?rq=1 but in practice isn't. the control I want is different – Stefano Borini Jan 28 '13 at 22:08
  • It's not that different what you want, really. – Martijn Pieters Jan 28 '13 at 22:16
  • @Martijn it is. I can't override excepthook, and I want control on baz, where the exception is generated – Stefano Borini Jan 28 '13 at 22:21
  • You want only the display to be trimmed, not the traceback itself. Right? – Keith Jan 28 '13 at 22:27
  • @keith: also the traceback. nothing must know of the existence of bar and baz. – Stefano Borini Jan 28 '13 at 22:28
  • ok, I think I've finally understood what you want: to raise the exception in baz but to make it look like it actually came from foo. You can't do that from bar or baz. Why not catch in foo and re-raise there (after all, foo _must_ know about bar at least)? – isedev Jan 28 '13 at 22:39
  • @isedev: I can't because bar and baz are actually decorators, and foo knows nothing about them – Stefano Borini Jan 28 '13 at 22:40
  • 1
    I think you need to restate your question more accurately. Your example is misleading... As it stands, foo() calls bar(), so it knows about it. Can you show some code which better represents your problem? – isedev Jan 28 '13 at 22:43
  • @isedev: you really don't want to see it. it's like monty python's funniest joke in the world. If you read it, you die. – Stefano Borini Jan 28 '13 at 22:46
  • The `raise` example you post doesn't work on Python, because the traceback is not built in advance. It is built lazily when the exception propagates. But it looks easy enough to add to `foo()` code like: `try: bar(); except Exception, e: raise e`, which would re-raise any exception from within itself rather than from wherever it really came from. – Armin Rigo Jan 29 '13 at 00:54

0 Answers0