Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #7168 > unrolled thread

Function call arguments in stack trace?

Started byDun Peal <dunpealer@gmail.com>
First post2011-06-07 11:09 -0700
Last post2011-06-07 23:45 -0300
Articles 7 — 5 participants

Back to article view | Back to comp.lang.python


Contents

  Function call arguments in stack trace? Dun Peal <dunpealer@gmail.com> - 2011-06-07 11:09 -0700
    Re: Function call arguments in stack trace? Neil Cerutti <neilc@norwich.edu> - 2011-06-07 18:23 +0000
      Re: Function call arguments in stack trace? Dun Peal <dunpealer@gmail.com> - 2011-06-07 12:31 -0700
        Re: Function call arguments in stack trace? Ian Kelly <ian.g.kelly@gmail.com> - 2011-06-07 13:52 -0600
        Re: Function call arguments in stack trace? Irmen de Jong <irmen.NOSPAM@xs4all.nl> - 2011-06-07 22:01 +0200
        Re: Function call arguments in stack trace? Neil Cerutti <neilc@norwich.edu> - 2011-06-07 20:29 +0000
    Re: Function call arguments in stack trace? "Gabriel Genellina" <gagsl-py2@yahoo.com.ar> - 2011-06-07 23:45 -0300

#7168 — Function call arguments in stack trace?

FromDun Peal <dunpealer@gmail.com>
Date2011-06-07 11:09 -0700
SubjectFunction call arguments in stack trace?
Message-ID<9d344c45-8017-4c80-9a17-bc7accd81047@l26g2000yqm.googlegroups.com>
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.

[toc] | [next] | [standalone]


#7170

FromNeil Cerutti <neilc@norwich.edu>
Date2011-06-07 18:23 +0000
Message-ID<9578lmFl76U1@mid.individual.net>
In reply to#7168
On 2011-06-07, Dun Peal <dunpealer@gmail.com> 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

[toc] | [prev] | [next] | [standalone]


#7175

FromDun Peal <dunpealer@gmail.com>
Date2011-06-07 12:31 -0700
Message-ID<6c3c9ab9-7880-4988-8258-8f8b2d4d7f72@m21g2000yqc.googlegroups.com>
In reply to#7170
On Jun 7, 1:23 pm, Neil Cerutti <ne...@norwich.edu> 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.

[toc] | [prev] | [next] | [standalone]


#7178

FromIan Kelly <ian.g.kelly@gmail.com>
Date2011-06-07 13:52 -0600
Message-ID<mailman.2541.1307476383.9059.python-list@python.org>
In reply to#7175
On Tue, Jun 7, 2011 at 1:31 PM, Dun Peal <dunpealer@gmail.com> wrote:
> On Jun 7, 1:23 pm, Neil Cerutti <ne...@norwich.edu> 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.

[toc] | [prev] | [next] | [standalone]


#7179

FromIrmen de Jong <irmen.NOSPAM@xs4all.nl>
Date2011-06-07 22:01 +0200
Message-ID<4dee83a9$0$49174$e4fe514c@news.xs4all.nl>
In reply to#7175
On 7-6-2011 21:31, Dun Peal wrote:
> On Jun 7, 1:23 pm, Neil Cerutti <ne...@norwich.edu> 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 (8), 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

[toc] | [prev] | [next] | [standalone]


#7183

FromNeil Cerutti <neilc@norwich.edu>
Date2011-06-07 20:29 +0000
Message-ID<957g1rF32aU1@mid.individual.net>
In reply to#7175
On 2011-06-07, Dun Peal <dunpealer@gmail.com> wrote:
> On Jun 7, 1:23?pm, Neil Cerutti <ne...@norwich.edu> 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

[toc] | [prev] | [next] | [standalone]


#7208

From"Gabriel Genellina" <gagsl-py2@yahoo.com.ar>
Date2011-06-07 23:45 -0300
Message-ID<mailman.12.1307500925.11593.python-list@python.org>
In reply to#7168
En Tue, 07 Jun 2011 15:09:54 -0300, Dun Peal <dunpealer@gmail.com>  
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

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web