解析未声明的Args

时间:2012-03-27 04:57:32

标签: python

我正在编写一个用于运行bash命令的实用程序,它实际上将字符串和列表可选参数作为输入,并使用可选参数来插入字符串。

我希望它能像这样工作:

interpolate.py Hello {user_arg} my name is {computer_arg} %% --user_arg=john --computer_arg=hal

%%是一个分隔符,它将要插入的字符串与参数分开。以下是用于插入字符串的参数。在这种情况下,用户选择user_argcomputer_arg作为参数。程序无法预先知道用户将选择哪个参数名称。

我的问题是如何解析参数?我可以在分隔符上简单地分割输入参数,但我无法弄清楚如何让optparse只是将可选参数列表作为字典给出,而不事先指定它们。有没有人知道如何在不写大量正则表达式的情况下做到这一点?

3 个答案:

答案 0 :(得分:2)

好吧,如果使用' - '将参数与参数而不是%%分开,optparse / argparse只会将参数作为普通列表(将它们视为位置参数而不是切换)。在那之后它不是'很多'正则表达式,它只是一个分裂:

for argument in args:
    if not argument.startswith("--"):
        # decide what to do in this case...
        continue
    arg_name, arg_value = argument.split("=", 1)
    arg_name = arg_name[2:]
    # use the argument any way you like

答案 1 :(得分:2)

使用argparse,您可以使用parse_known_args方法来使用预定义的参数和任何其他参数。例如,使用以下脚本

import sys
import argparse

def main(argv=None):

    parser = argparse.ArgumentParser()

    parser.add_argument('string', type=str, nargs='*',
        help="""String to process. Optionally with interpolation
                (explain this here...)""")

    args, opt_args = parser.parse_known_args(argv)

    print args
    print opt_args

    return 0

if __name__=='__main__':
    sys.exit(main(sys.argv[1:]))

并使用

进行调用
python script.py Hello, my name is {name} --name=chris

产生以下输出:

Namespace(string=['Hello,' 'my', 'name', 'is', '{name}'])
['--name=chris']

剩下要做的就是遍历args命名空间,查找{...}形式的字符串,并将其替换为opt_args中的相应元素(如果存在)。 (我不确定argparse是否可以自动进行参数插值,上面的例子是我想到的唯一直接解决方案)。

答案 2 :(得分:1)

对于这样的事情,你真的不需要optparse或argparse - 这种情况下这些库的好处很少使用(比如孤独的-v类型参数,检查无效选项,值验证和等等)

def partition_list(lst, sep):
    """Slices a list in two, cutting on index matching "sep"

    >>> partition_list(['a', 'b', 'c'], sep='b')
    (['a'], ['c'])
    """
    if sep in lst:
        idx = lst.index(sep)
        return (lst[:idx], lst[idx+1:])
    else:
        return (lst[:], )

def args_to_dict(args):
    """Crudely parses "--blah=123" type arguments into dict like
    {'blah': '123'}
    """
    ret = {}
    for a in args:
        key, _, value = a.partition("=")
        key = key.replace("--", "", 1)
        ret[key] = value

    return ret


if __name__ == '__main__':
    import sys

    # Get stuff before/after the "%%" separator
    string, args = partition_list(sys.argv[1:], "%%")

    # Join input string
    string_joined = " ".join(string)

    # Parse --args=stuff
    d = args_to_dict(args)

    # Do string-interpolation
    print string_joined.format(**d)