optparser question
Steven Bethard
steven.bethard at gmail.com
Fri Dec 22 10:32:42 EST 2006
Michele Petrazzo wrote:
> I'm trying optparse and I see a strange (for me) behavior:
>
> def store_value(option, opt_str, value, parser):
> setattr(parser.values, option.dest, value)
>
> parser = optparse.OptionParser()
> parser.add_option("-f", "--foo",
> action="callback", callback=store_value,
> type="int", dest="foo")
>
> args = ["-f", "1"]
> (options, args) = parser.parse_args(args)
> print options, args
>
> {'foo': 1} [] # with the type
> {'foo': None} ['1'] #without it
>
> If I not specify the type in add_options, the value aren't passed to the
> store_value (into value variable), but it's understood as args!
> If I specify it, it
>
> Is this normal?
I believe so. The optparse module lists 'callback' as one of the
TYPED_ACTIONS but not one of the ALWAYS_TYPED_ACTIONS, so it should only
set nargs=1 if a type= argument was provided. That means that callbacks
will be assumed to take zero arguments until you pass an nargs= or a
type= argument.
You can try using argparse_, which doesn't make these weird inferences,
and generally assumes that your action will take a single argument
unless you specify otherwise::
>>> import argparse
>>> class StoreValue(argparse.Action):
... def __call__(self, parser, namespace, value, opt_str=None):
... setattr(namespace, self.dest, value)
...
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('-f', '--foo', action=StoreValue)
>>> parser.parse_args('-f 1'.split())
Namespace(foo='1')
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('-f', '--foo', action=StoreValue, type=int)
>>> parser.parse_args('-f 1'.split())
Namespace(foo=1)
Not sure exactly what your callback was trying to do though -- it seems
like you're just duplicating the 'store' action (which is the default
anyway).
FWIW, if you want to write a custom action in argparse, you don't have
to worry about the weird TYPED_ACTIONS kinds of things in optparse.
Just specify in the action's constructor whatever defaults you need, e.g.::
>>> class MyStoreValue(argparse.Action):
... def __init__(self, nargs=2, type=int, **kwargs):
... superinit = super(MyStoreValue, self).__init__
... superinit(nargs=nargs, type=type, **kwargs)
... def __call__(self, parser, namespace, value, opt_str=None):
... setattr(namespace, self.dest, value)
...
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('-f', '--foo', action=MyStoreValue)
>>> parser.parse_args('-f 1 2'.split())
Namespace(foo=[1, 2])
Of course, you can always specify nargs= and type= in the
``add_argument()`` call too.
.. _argparse: http://argparse.python-hosting.com/
STeVe
More information about the Python-list
mailing list