Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Function call arguments in stack trace?

Reply
Thread Tools

Function call arguments in stack trace?

 
 
Dun Peal
Guest
Posts: n/a
 
      06-07-2011
Hi,

In a stack trace, is it possible to somehow get the arguments with
which each function was called?

So for example, if function `foo` in module `bar` was called with
arguments `(1, [2])` when it raised an exception, then instead of:

Traceback (most recent call last):
File "bar.py", line 123, in foo
build_rpms()

The stack trace would read:

Traceback (most recent call last):
File "bar.py", line 123, in foo(1, [2])
build_rpms()

This would save a lot of debugging time!

Thanks, D.
 
Reply With Quote
 
 
 
 
Neil Cerutti
Guest
Posts: n/a
 
      06-07-2011
On 2011-06-07, Dun Peal <(E-Mail Removed)> wrote:
> Hi,
>
> In a stack trace, is it possible to somehow get the arguments with
> which each function was called?
>
> So for example, if function `foo` in module `bar` was called with
> arguments `(1, [2])` when it raised an exception, then instead of:
>
> Traceback (most recent call last):
> File "bar.py", line 123, in foo
> build_rpms()
>
> The stack trace would read:
>
> Traceback (most recent call last):
> File "bar.py", line 123, in foo(1, [2])
> build_rpms()
>
> This would save a lot of debugging time!


Use pdb.

--
Neil Cerutti
 
Reply With Quote
 
 
 
 
Dun Peal
Guest
Posts: n/a
 
      06-07-2011
On Jun 7, 1:23*pm, Neil Cerutti <(E-Mail Removed)> wrote:
> Use pdb.


Neil, thanks for the tip; `pdb` is indeed a great debugging tool.

Still, it doesn't obviate the need for arguments in the stack trace.
For example:

1) Arguments in stack trace can expedite a debugging session, and even
obviate it completely: "Why did `foo()` fail? Oh, because it got `-1`
as its first argument, while I only coded for positive integers!".
2) In some environments, it's very hard to recreate a rare exception
and analyze it with `pdb`. For instance, on a web application that
emails the stack traces of unhandled exceptions, it's very important
for that stack trace to be as informative as possible, since often
that's the only debugging feedback you will get.

Hope that makes sense, D.
 
Reply With Quote
 
Ian Kelly
Guest
Posts: n/a
 
      06-07-2011
On Tue, Jun 7, 2011 at 1:31 PM, Dun Peal <(E-Mail Removed)> wrote:
> On Jun 7, 1:23*pm, Neil Cerutti <(E-Mail Removed)> wrote:
>> Use pdb.

>
> Neil, thanks for the tip; `pdb` is indeed a great debugging tool.
>
> Still, it doesn't obviate the need for arguments in the stack trace.


Your program could use sys.excepthook to generate a custom stack trace
for unhandled exceptions. All the stack frames are available from the
traceback, but extracting the arguments would be tricky, and getting
the original arguments would be impossible if they've been reassigned
prior to the exception being raised. It would be simpler just to dump
all the locals in the frame.
 
Reply With Quote
 
Irmen de Jong
Guest
Posts: n/a
 
      06-07-2011
On 7-6-2011 21:31, Dun Peal wrote:
> On Jun 7, 1:23 pm, Neil Cerutti <(E-Mail Removed)> wrote:
>> Use pdb.

>
> Neil, thanks for the tip; `pdb` is indeed a great debugging tool.
>
> Still, it doesn't obviate the need for arguments in the stack trace.


If you can't use pdb perhaps you can use the following:

Pyro has always had a feature that prints detailed stacktraces. It is mainly meant to
clarify stacktraces that occur on a different machine (where you don't have the option
of using pdb), but can very well be used for normal code too:


import sys
import Pyro4.util
Pyro4.config.DETAILED_TRACEBACK=True
sys.excepthook=Pyro4.util.excepthook

def divide(a,b):
return a//b

def dividebysomething(a):
return divide(a,0)

print dividebysomething(10)


When you run this, this will be printed:

[E:\projects]python trace.py
--------------------------------------------------
<<type 'exceptions.ZeroDivisionError'>> RAISED : integer division or modulo by zero
Extended stacktrace follows (most recent call last)
--------------------------------------------------
File "trace.py", line (13), in <module>
Source code:
print dividebysomething(10)
File "trace.py", line (11), in dividebysomething
Source code:
return divide(a,0)
Local values:
a = 10
--------------------------------------------------
File "trace.py", line (, in divide
Source code:
return a//b
Local values:
a = 10
b = 0
--------------------------------------------------
<<type 'exceptions.ZeroDivisionError'>> RAISED : integer division or modulo by zero
--------------------------------------------------


You can find the relevant code that produces these kinds of tracebacks in the util.py
source file of Pyro. You can get that from Pypi:
http://pypi.python.org/pypi/Pyro4/
or the file directly from subversion:
$ svn export svn://svn.razorvine.net/Pyro/Pyro4/trunk/src/Pyro4/util.py

Perhaps you can use this or adapt it to suit your needs.


Irmen de Jong
 
Reply With Quote
 
Neil Cerutti
Guest
Posts: n/a
 
      06-07-2011
On 2011-06-07, Dun Peal <(E-Mail Removed)> wrote:
> On Jun 7, 1:23?pm, Neil Cerutti <(E-Mail Removed)> wrote:
>> Use pdb.

>
> Neil, thanks for the tip; `pdb` is indeed a great debugging
> tool.
>
> Still, it doesn't obviate the need for arguments in the stack
> trace. For example:
>
> 1) Arguments in stack trace can expedite a debugging session, and even
> obviate it completely: "Why did `foo()` fail? Oh, because it got `-1`
> as its first argument, while I only coded for positive integers!".
> 2) In some environments, it's very hard to recreate a rare exception
> and analyze it with `pdb`. For instance, on a web application that
> emails the stack traces of unhandled exceptions, it's very important
> for that stack trace to be as informative as possible, since often
> that's the only debugging feedback you will get.
>
> Hope that makes sense, D.


The locals should be in the frame object of the traceback. Here's
a sketch of a decorator to print them out before your program
bombs:

import sys

def report_arg_info(fn):
def wrapper(*arg, **kw):
try:
return fn(*arg, **kw)
except:
frame = sys.exc_info()[2].tb_next.tb_frame
print(frame.f_locals)
raise
return wrapper

Use it as usual:

@report_arg_info
def my_func(bombs)
raise ValueError

You could log the local arguments instead.

--
Neil Cerutti
 
Reply With Quote
 
Gabriel Genellina
Guest
Posts: n/a
 
      06-08-2011
En Tue, 07 Jun 2011 15:09:54 -0300, Dun Peal <(E-Mail Removed)>
escribió:

> In a stack trace, is it possible to somehow get the arguments with
> which each function was called?
>
> So for example, if function `foo` in module `bar` was called with
> arguments `(1, [2])` when it raised an exception, then instead of:
>
> Traceback (most recent call last):
> File "bar.py", line 123, in foo
> build_rpms()
>
> The stack trace would read:
>
> Traceback (most recent call last):
> File "bar.py", line 123, in foo(1, [2])
> build_rpms()
>
> This would save a lot of debugging time!


The cgitb module does exactly that; some third-party modules offer similar
functionality, but I don't remember any names.
Despite its name, cgitb works with any script.

Given this test script:

# begin test_traceback.py
import cgitb
cgitb.enable(format="text")

spam = []

def a(x, y):
"This is function a"
z = x+y
return b(z)


def b(z, n=3):
"""This is function b.

Its docstring is longer."""

if n!=3:
just(to_consume_space)

w = c(foo=z*n)

return w


def c(foo=0, bar=1):
"This is function c"
baz = foo+bar
spam.somenamethatdoesnotexist(foo+bar)
anotherglobal("thatdoesnotexisteither")

a(10, 20)
# end test_traceback.py

the output is:


AttributeError
Python 3.2: d:\apps\Python32\python.exe
Tue Jun 7 23:36:36 2011

A problem occurred in a Python script. Here is the sequence of
function calls leading up to the error, in the order they occurred.

D:\TEMP\test_traceback.py in <module>()
27 baz = foo+bar
28 spam.somenamethatdoesnotexist(foo+bar)
29 anotherglobal("thatdoesnotexisteither")
30
31 a(10, 20)
a = <function a>

D:\TEMP\test_traceback.py in a(x=10, y=20)
7 "This is function a"
8 z = x+y
9 return b(z)
10
11
global b = <function b>
z = 30

D:\TEMP\test_traceback.py in b(z=30, n=3)
18 just(to_consume_space)
19
20 w = c(foo=z*n)
21
22 return w
w undefined
global c = <function c>
foo undefined
z = 30
n = 3

D:\TEMP\test_traceback.py in c(foo=90, bar=1)
26 "This is function c"
27 baz = foo+bar
28 spam.somenamethatdoesnotexist(foo+bar)
29 anotherglobal("thatdoesnotexisteither")
30
global spam = []
spam.somenamethatdoesnotexist undefined
foo = 90
bar = 1
AttributeError: 'list' object has no attribute 'somenamethatdoesnotexist'
[... exception attributes ...]
[... original traceback ...]

--
Gabriel Genellina

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
C/C++ compilers have one stack for local variables and return addresses and then another stack for array allocations on the stack. Casey Hawthorne C Programming 3 11-01-2009 08:23 PM
How to call function whose function call with arguments is in astring Options grbgooglefan C Programming 4 01-30-2008 05:12 PM
How to call function whose function call with arguments is in astring grbgooglefan C++ 2 01-30-2008 07:18 AM
How to call function whose function call with arguments is in astring Options grbgooglefan C Programming 0 01-30-2008 04:19 AM
defined? for recursive function call v/s defined? for function call stack Alok Ruby 3 04-13-2006 11:53 AM



Advertisments