Printing literal text of an argument

R

Rex Eastbourne

Hi all,

I've written the following simple macro called debug(aname, avalue)
that prints out the name of an expression and its value:

def debug(aname, avalue):
print aname, 'is':
pprint.pprint(avalue)

An example call is:

debug('compose(f1,f2)', compose(f1,f2))

Writing the exact same thing twice (one in quotes and the other not)
sets off an alarm in my head. Is there a way to make this function take
only one argument, and use both its value and its literal form? On a
slightly different topic, is it also possible to make the macro print
the line number where the function was first called?

Thanks,

Rex
 
J

Jeremy Moles

def debug(s):
print "s"
exec(s)

The line thing i'm not so sure about. Er. Hmmm.
 
G

Gregory Bond

Rex said:
def debug(aname, avalue):
print aname, 'is':
pprint.pprint(avalue)

use eval:

def debug(s):
print s, 'is'
pprint.pprint(eval(s))

(it does mean the arg is a string not code......)
On a
slightly different topic, is it also possible to make the macro print
the line number where the function was first called?

You can raise and catch an exception then walk up the call stack:

import sys

def debug(s):
print s, 'is'
pprint.pprint(eval(s))

try:
raise ""
except:
tb = sys.exc_info()[2]
# Find the calling frame
frame = tb.tb_frame.f_back
print "Called from line", frame.f_lineno

See the language reference manual sec 3.2 "Standard Type Hierarchy".
 
M

Mike Meyer

[Format recovered from top posting]

Jeremy Moles said:
def debug(s):
print "s"
exec(s)

Um, no. First, I'm pretty sure you mean "print s" for the print
statement. The one you have just prints a single s. Second, exec is a
statement, not a function. The correct syntax is "exec s". The one you
used works, because an expression in parenthesies evaluates to the
value of the expression. Finally, doing an "exec s" doesn't display a
value - you need to print the results of the exec, which you can't
do. You want to use an eval here, not an exec. Eval is a function, and
returns a value. It's limited to expressions. Which will meet Rex's
stated requirements.

Of course, all this is moot because the eval (exec) happens in a
different context than the call, so the results can be radically
different than what you expect:
.... print s
.... print eval(s)
.... .... x = 3
.... debug("x")
.... x
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in foo
File "<stdin>", line 3, in debug

See what I mean?

You really need to pass the context to debug for it to get the right
thing:
.... print x
.... print eval(x, glob, loc)
.... .... x = 3
.... debug("x", globals(), locals())
....

You can figure out the locals via introspection (see the help for the
inspect module for more details). I'm not sure if there's a similar
way to figure out what the globals were at the point that debug is
called.

<mike
 
R

Rex Eastbourne

Thanks. I adapted it a bit:

def debug(foo):
print foo, 'is:'
exec('pprint.pprint(' + foo + ')')

But I'm getting "NameError: name 'foo' is not defined," since foo is
not defined in this scope. (The function works beautifully when I'm
dealing with global variables, which is very rarely).

Any way around this?

Rex
 
R

Reinhold Birkenfeld

Rex said:
Thanks. I adapted it a bit:

def debug(foo):
print foo, 'is:'
exec('pprint.pprint(' + foo + ')')

But I'm getting "NameError: name 'foo' is not defined," since foo is
not defined in this scope. (The function works beautifully when I'm
dealing with global variables, which is very rarely).

Any way around this?

Eh, yes, but it's getting uglier...

def debug(foo):
print foo, 'is:'
frame = sys._getframe(-1)
exec 'pprint.pprint(%s)' % foo, frame.f_globals, frame.f_locals

Untested.

Reinhold
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,262
Messages
2,571,311
Members
47,986
Latest member
ColbyG935

Latest Threads

Top