Parsing variables out of python lines

Bengt Richter bokr at oz.net
Mon Oct 7 04:05:51 EDT 2002


On Mon, 07 Oct 2002 05:43:54 GMT, Mark <Hobbes2176 at yahoo.com> wrote:

>I hate finding answer quickly after posting.  Anyway, here is code that will
>solve my problem:
>
>
>import tokenize
>import StringIO
>
>foo = [1,2,3]
>x = "for i in foo:"
>
>#
>#The StringIO trick turns a string into a read'able object (or so it seems)
>#
>t = tokenize.generate_tokens(StringIO.StringIO(x).readline)
>
>for junk, item, rest1, rest2, rest3 in t:
>    if item in vars():
>        print eval(item),
>    else:
>        print item,
>print
>
>With output:
>==> for i in [1, 2, 3] :
>
>Anyone know how to clean up the tuple assignment (I only want item, the rest 
>could go to /dev/null if they want).
>
Not sure what you're doing in your larger context, but extracting the second item
from each tuple is easy with a list comprehension (see below). If the sequence is
really huge, you could wrap tokenize in a generator to return the selected tuple
element. (See further below).
 
(BTW, if you know that item in vars() is true, why not just look it up with vars()[item]?)

 >>> import tokenize
 >>> import StringIO
 >>> foo = [1,2,3]
 >>> x = "for i in foo:"
 >>> items = [tup[1] for tup in tokenize.generate_tokens(StringIO.StringIO(x).readline)]
 >>> print ' '.join([(z in vars() and [`vars()[z]`] or [z])[0] for z in items])
 for i in [1, 2, 3] :

Though you might want to do `` to all the output so you can distinguish better (and see the ''):
>>> print ' '.join([`(z in vars() and [vars()[z]] or [z])[0]` for z in items])
'for' 'i' 'in' [1, 2, 3] ':' ''

or if you don't mind the brackets and commas, just let the list be repr'd
>>> print [(z in vars() and [vars()[z]] or [z])[0] for z in items]
['for', 'i', 'in', [1, 2, 3], ':', '']

The generator lets you put "in tokitems(x,1)" in place of "in items" above:

 >>> from __future__ import generators
 >>> def tokitems(s, i):
 ...     for tup in tokenize.generate_tokens(StringIO.StringIO(s).readline):
 ...         yield tup[i]
 ...
 >>> print ' '.join([`(z in vars() and [vars()[z]] or [z])[0]` for z in tokitems(x,1)])
 'for' 'i' 'in' [1, 2, 3] ':' ''

Or, less obscure and avoiding the ugly substitute for (x?y:z),

 >>> for item in tokitems(x,1):
 ...     try:
 ...         print `vars()[item]`,
 ...     except KeyError:
 ...         print `item`,
 ...
 'for' 'i' 'in' [1, 2, 3] ':' ''

(I can't add the final dedented bare "print" interactively on the next line for
some reason. If it's waiting for a blank line, why can't it wait for that blank
line and decide *then* whether I've done badly with the dedent? It would make
for cleaner example-typing. I can get around it by putting everything indented
under an "if 1:" but IMO that's a warty restriction.)

Regards,
Bengt Richter



More information about the Python-list mailing list