Get Only the Last Items in a Traceback

Peter Otten __peter__ at web.de
Wed Sep 12 11:17:14 CEST 2007


Am Wed, 12 Sep 2007 02:09:28 +0000 schrieb gregpinero at gmail.com:

> I'm running code via the "exec in context" statement within a much
> larger program.  What I would like to do is capture any possible
> errors and show a pretty traceback just like the Python interactive
> interpreter does, but only show the part of the traceback relating to
> the code sent to exec.
> 
> For example here is the code I'm using:
> 
> try:
>     exec code
> except Exception,Err:
>     traceback.print_exc()
> 
> Which gives me something like this when it catches an exception:
> 
> Traceback (most recent call last):
>   File "/....py", line 843, in run
>     semi_safe_exec.safe_eval(code.replace('\r',''),context,5)
>   File ".....py", line 400, in safe_eval
>     exec_timed(code, context, timeout_secs)
>   File ".....py", line 353, in exec_timed
>     exec code in context
>   File "<string>", line 7, in ?
>   File "<string>", line 5, in func2
>   File "<string>", line 2, in func1
> ZeroDivisionError: integer division or modulo by zero
> 
> What I want to print instead is just something like:
> 
> Traceback (most recent call last):
>   File "<string>", line 7, in ?
>   File "<string>", line 5, in func2
>   File "<string>", line 2, in func1
> ZeroDivisionError: integer division or modulo by zero
> 
> Thanks in advance for the help.
> 
> -Greg
> 
> P.S. if it matters, for this example, code in exec code is:
> 
> def func1():
>     print 7/0
> 
> def func2():
>     func1()
> 
> func2()

Your assessment is wrong. You only get the extra lines in the traceback if
you don't immediately wrap the exec statement in a try ... except block:

$ cat snip_traceback1.py
import traceback

def alpha():
    try:
        beta()
    except Exception, e:
        traceback.print_exc()

def beta():
    gamma()

def gamma():
    exec s in {}

s = """ 
def delta():
    epsilon()
    
def epsilon():
    1/0
delta()
"""

if __name__ == "__main__":
    alpha()

$ python snip_traceback1.py 
Traceback (most recent call last):
  File "snip_traceback1.py", line 5, in alpha
    beta()
  File "snip_traceback1.py", line 10, in beta
    gamma()
  File "snip_traceback1.py", line 13, in gamma
    exec s in {}
  File "<string>", line 7, in <module>
  File "<string>", line 3, in delta
  File "<string>", line 6, in epsilon
ZeroDivisionError: integer division or modulo by zero

So the first step is to move the try ... except closer to the exec:

$ cat snip_traceback2.py
import traceback

def alpha():
    beta()

def beta():
    gamma()

def gamma():
    try:
        exec s in {}
    except Exception, e:
        traceback.print_exc()

s = """ 
def delta():
    epsilon()
    
def epsilon():
    1/0
delta()
"""

if __name__ == "__main__":
    alpha()

$ python snip_traceback2.py 
Traceback (most recent call last):
  File "snip_traceback2.py", line 11, in gamma
    exec s in {}
  File "<string>", line 7, in <module>
  File "<string>", line 3, in delta
  File "<string>", line 6, in epsilon
ZeroDivisionError: integer division or modulo by zero

You are almost there. Now let's strip off the outermost traceback:

$ cat snip_traceback3.py
import sys
import traceback

def alpha():
    beta()

def beta():
    gamma()

def gamma():
    try:
        exec s in {}
    except Exception, e:
        etype, value, tb = sys.exc_info()
        traceback.print_exception(etype, value, tb.tb_next)

s = """ 
def delta():
    epsilon()
    
def epsilon():
    1/0
delta()
"""

if __name__ == "__main__":
    alpha()

$ python snip_traceback3.py 
Traceback (most recent call last):
  File "<string>", line 7, in <module>
  File "<string>", line 3, in delta
  File "<string>", line 6, in epsilon
ZeroDivisionError: integer division or modulo by zero

Heureka.

Peter



More information about the Python-list mailing list