views:

219

answers:

2

I have python code something like:

from string import Template
import optparse

def main():
  usage = "usage: %prog options outputname"
  p = optparse.OptionParser(usage)
  p.add_option('--optiona', '-a', default="")
  p.add_option('--optionb', '-b', default="")
  options, arguments = p.parse_args()
  t = Template('Option a is ${optiona} option b is ${optionb}')
  print t.substitute(options)

But that gives me

AttributeError: Values instance has no attribute '__getitem__'

Because options is a Values and not a dictionary.

How do I neatly make this work?

(any other suggestions welcome, my pythonic sense is still being nurtured...)

+3  A: 

The following appears to work for me:

from string import Template
import optparse

def main():
    usage = "usage: %prog options outputname"
    p = optparse.OptionParser(usage)
    p.add_option('--optiona', '-a', default="")
    p.add_option('--optionb', '-b', default="")
    options, arguments = p.parse_args()
    t = Template('Option a is ${optiona} option b is ${optionb}')
    print t.substitute(vars(options)) #I'm assuming the uppercase S was a typo.
RoadieRich
thanks. I knew it'd only be a few characters...
Greg
+4  A: 

OptionParser.parse_args returns an object with the option variable names as attributes, rather than as dictionary keys. The error you're getting means that options does not support subscripting, which it would normally do by implementing __getitem__.

So, in other words, your options are at:

options.optiona
options.optionb

Rather than:

options['optiona']
options['optionb']

Template variable substitution expects a dict-like interface, so it's trying to find optiona and optionb using the latter approach.

Use vars as RoadieRich suggests in his answer to make the template substitution approach work. Alternatively, unless you really need a Template object, I'd recommend using a simple print:

print 'Option a is %s and option b is %s' % (options.optiona, options.optionb)

You can also combine the two approaches if you feel that named string parameters are better:

print 'Option a is %(optiona)s and option b is %(optionb)s' % vars(options)
Jarret Hardie
IIRC, the only problem with the "traditional" substitution is that is it's being deprecated in Python 3.1.
RoadieRich
Your first suggestion doesn't work so well for me, since there are actually 7 options, and the text to substitute them into is ~50 lines. But thanks for the explanation.
Greg