I'm writing a python script which I would like to be able to both call from the command line and import as a library function. Ideally the command line options and the function should use the same set of default values. What is the best way to allow me to reuse a single set of defaults in both places?
Here's the current code with duplicate defaults.
from optparse import OptionParser
def do_stuff(opt1="a", opt2="b", opt3="c"):
    print opt1, opt2, opt3
if __name__ == "__main__":
    parser = OptionParser()
    parser.add_option("--opt1", default="a")
    parser.add_option("--opt2", default="b")
    parser.add_option("--opt3", default="c")
    #parser.set_defaults(opt1="a")
    options, args = parser.parse_args()
    do_stuff(*args, **vars(options))
                Deprecated since version 3.2: The optparse module is deprecated and will not be developed further; development will continue with the argparse module.
If you plan to be a software developer with Python, you'll want to be able to use argparse for your scripting needs. If you're a data scientist, you'll likely find yourself needing to port your code from a Jupyter Notebook to a reproducible script.
Optparse module makes easy to write command-line tools. It allows argument parsing in the python program. optparse make it easy to handle the command-line argument. It comes default with python. It allows dynamic data input to change the output.
The store_true option automatically creates a default value of False. Likewise, store_false will default to True when the command-line argument is not present. The source for this behavior is succinct and clear: http://hg.python.org/cpython/file/2.7/Lib/argparse.py#l861.
I'd handle it by introspecting the function of interest to set options and defaults appropriately. For example:
import inspect
from optparse import OptionParser
import sys
def do_stuff(opt0, opt1="a", opt2="b", opt3="c"):
    print opt0, opt1, opt2, opt3
if __name__ == "__main__":
    parser = OptionParser()
    args, varargs, varkw, defaults = inspect.getargspec(do_stuff)
    if varargs or varkw:
      sys.exit("Sorry, can't make opts from a function with *a and/or **k!")
    lend = len(defaults)
    nodef = args[:-lend]
    for a in nodef:
      parser.add_option("--%s" % a)
    for a, d in zip(args[-lend:], defaults):
      parser.add_option("--%s" % a, default=d)
    options, args = parser.parse_args()
    d = vars(options)
    for n, v in zip(nodef, args):
      d[n] = v
    do_stuff(**d)
                        Here's the solution - it's trivial if you only need keyword arguments - just use locals.update. Following handles both, positional and key word args (key word args overrides positional).
from optparse import OptionParser
ARGS = {'opt1': 'a', 
        'opt2': 'b',
        'opt3': 'c'}
def do_stuff(*args, **kwargs):
    locals = ARGS
    keys = ARGS.keys()
    keys.sort()
    if args:
        for key,arg in zip(keys,args):
            locals.update({key: arg})
    if kwargs:
        locals.update(kwargs)
    print locals['opt1'], locals['opt2'], locals['opt3']
if __name__ == "__main__":
    parser = OptionParser()
    for key,default in ARGS.items():
        parser.add_option('--%s' % key, default='%s' % default)
    options, args = parser.parse_args()
    do_stuff(*args, **vars(options))
    do_stuff()
    do_stuff('d','e','f')
    do_stuff('d','e','f', opt3='b')
    do_stuff(opt1='c', opt2='a', opt3='b')
Output:
a b c 
a b c 
d e f 
d e b 
c a b 
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With