[Tutor] How do I do this in python?

Emile van Sebille emile at fenx.com
Thu Jun 11 17:37:38 CEST 2009


On 6/11/2009 4:08 AM Kent Johnson said...
> On Wed, Jun 10, 2009 at 9:43 PM, Robert Lummis<robert.lummis at gmail.com> wrote:
>> I want to write a function that I can use for debugging purposes that
>> prints the values of whatever list of object references it is given as
>> arguments, without knowing in advance how many object references it
>> will be called with or what they might be. For example, the call:
>> show(a,b,c) would output the values of the arguments like this:
>>
>>    a = 3
>>    b = 'john'
>>    c = 'Monday'
>>
>> while show (x) would output (for example):
>>
>>    x = 3.14
>>
>> of course displaying whatever the actual current values are. For a
>> collection object it would make sense to output just the first few
>> values.
>>
>> So within the 'show' function definition I have to somehow get a list
>> of the literal argument names it was called with and then use the
>> names as globals to get the values. How do I do that?
> 
> I don't know of a straightforward way to do this. You can use
> sys._getframe() to get the caller's context but I don't think it will
> tell you what variables were used for the call.
> 

Well, kind of.  And somewhat OK for simple variables.

OK.  Let's see what's in _getframe...

 >>> import sys

... and a quick function to return _getframe from within a function

 >>> def rframe(*args,**kwargs): return sys._getframe()

... now to get one

 >>> a,b,c = 1,2,3
 >>> xx = rframe(a,b,c)

...a bit of digging and we find these two...

 >>> xx.f_locals
{'args': (1, 2, 3), 'kwargs': {}}

 >>> xx.f_back.f_code.co_names
('rframe', 'a', 'b', 'c', 'xx')

So, a <cleaned up> first cut at show...

import sys
from pprint import pprint

def show(*args):
     F = sys._getframe()
     argnames = list(F.f_back.f_code.co_names)
     argnames = argnames[argnames.index('show')+1:]
     argvals = F.f_locals['args']
     pprint( zip(argnames,argvals) )

... and some interactive testing...

 >>> a,b,c = 1,2,3
 >>> show(a,b,c)
[('a', 1), ('b', 2), ('c', 3)]
 >>> show(d,e,a,b)
[('d', 4), ('e', 5), ('a', 1), ('b', 2)]
 >>> L = [1,2,3]
 >>> show(d,e,a,b,L)
[('d', 4), ('e', 5), ('a', 1), ('b', 2), ('L', [1, 2, 3])]

... but watch out for composite objects...

 >>> show(d,e,a,b,L[0])
[('d', 4), ('e', 5), ('a', 1), ('b', 2), ('L', 1)]

 >>> D = dict([('d', 4), ('e', 5), ('a', 1), ('b', 2), ('L', 1)])
 >>> D['L']
1
 >>> show(d,e,a,b,D['L'])
[('d', 4), ('e', 5), ('a', 1), ('b', 2), ('D', 1)]

I wouldn't rely on this, but it may be of some use and shows a little of 
the introspection abilities python provides.

Emile





More information about the Tutor mailing list