Printing literal text of an argument

Mike Meyer mwm at mired.org
Thu Aug 11 22:13:43 EDT 2005


[Format recovered from top posting]

Jeremy Moles <jeremy at emperorlinux.com> writes:
> On Thu, 2005-08-11 at 14:04 -0700, Rex Eastbourne wrote:
>> 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?
> 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:

>>> def debug(s):
...  print s
...  print eval(s)
... 
>>> def foo():
...  x = 3
...  debug("x")
... 
>>> foo()
x
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 3, in foo
  File "<stdin>", line 3, in debug
  File "<string>", line 1, in ?
NameError: name 'x' is not defined
>>> 

See what I mean?

You really need to pass the context to debug for it to get the right
thing:

>>> def debug(x, glob, loc):
...  print x
...  print eval(x, glob, loc)
... 
>>> def foo():
...  x = 3
...  debug("x", globals(), locals())
... 
>>> foo()
x
3
>>> 

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
-- 
Mike Meyer <mwm at mired.org>			http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.



More information about the Python-list mailing list