Python optparse по умолчанию против функций по умолчанию - PullRequest
6 голосов
/ 03 октября 2009

Я пишу скрипт на python, который я хотел бы иметь возможность вызывать из командной строки и импортировать как библиотечную функцию. В идеале параметры командной строки и функция должны использовать один и тот же набор значений по умолчанию. Как лучше всего разрешить мне повторно использовать один набор значений по умолчанию в обоих местах?

Вот текущий код с повторяющимися значениями по умолчанию.

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))

Ответы [ 3 ]

3 голосов
/ 03 октября 2009

Я бы справился с этим, проанализировав интересующую функцию, чтобы соответствующим образом установить параметры и значения по умолчанию. Например:

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)
2 голосов
/ 03 октября 2009

Решение Алекса проверить очень мощно!

Для легких программ вы также можете просто использовать это:

def do_stuff(opt1="a", opt2="b", opt3="c"):
    print opt1, opt2, opt3

if __name__ == "__main__":
    from optparse import OptionParser
    opts = do_stuff.func_defaults
    parser = OptionParser()    
    parser.add_option("--opt1", default=opts[0], help="Option 1 (%default)")
    parser.add_option("--opt2", default=opts[1], help="Option 2 (%default)")
    parser.add_option("--opt3", default=opts[2], help="Option 3 (%default)")

    options, args = parser.parse_args()

    do_stuff(*args, **vars(options))
2 голосов
/ 03 октября 2009

Вот решение - это тривиально, если вам нужны только ключевые аргументы - просто используйте locals.update. Следующие дескрипторы - как позиционные, так и ключевые аргументы (ключевые слова - переопределяют позиционные).

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')

Выход:

a b c 
a b c 
d e f 
d e b 
c a b 
...