解析多个子分析符,但具有全局参数

时间:2014-12-08 08:23:33

标签: python argparse

我已经阅读了很多关于如何定义,解析和运行多个子运算符的问题和答案,如

tool.py func_a -a 12 func_b -b 15 input.txt output.txt
                                  ^-- main parser args
                     ^--------------- subparser b
        ^---------------------------- subparser a

他们通常会建议:

def func_a(args):
    pass

def func_b(args):
    pass


parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()

# Define subparsers
subp_a = subparsers.add_parser(func_a.__name__)
subp_a.set_defaults(func=func_a)
subp_a.add_argument('-a')

subp_b = subparsers.add_parser(func_b.__name__)
subp_b.set_defaults(func=func_b)
subp_b.add_argument('-b')

# Define global parameters
parser.add_argument('input', type=argparse.FileType('r'))
parser.add_argument('output', type=argparse.FileType('wb', 0))

# Parse and run through all arguments
rest = sys.argv[1:]
while rest:
    args, rest = parser.parse_known_args(rest)
    args.func(args)

但是,这个实现有一个问题:参数inputoutput是为主解析器定义的,应该只使用一次。但是,每次调用parser.parse_known_args(rest)都需要设置值,然后将其从rest中删除。

这意味着第一次调用parse_known_args会检索值,并且由于缺少参数,每次后续调用都会失败。

有没有解决方法可以解决这个问题,而无需手动将值复制到rest列表中?

1 个答案:

答案 0 :(得分:0)

是的,第一个parse_known_args会消耗文件名以及第一个子分析器级别。

您可以定义2个解析器,其中一个使用' global'定位,一个没有。首先使用'解析'解析器,挂在args上(用于文件名)。然后使用'在没有'的情况下沿着subparser堆栈工作。解析器。

这是一个更简单的例子:

parser = argparse.ArgumentParser()
parser.add_argument('foo')
subp = parser.add_subparsers(dest='cmd')
cmd1 = subp.add_parser('cmd1')
cmd1.add_argument('-a')
cmd2 = subp.add_parser('cmd2')
# parser.add_argument('bar')  # confusing location

parser1 = argparse.ArgumentParser()
subp = parser1.add_subparsers(dest='cmd')
cmd1 = subp.add_parser('cmd1', parents=[cmd1], add_help=False)
cmd2 = subp.add_parser('cmd2')

# Parse and run through all arguments
args, rest = parser.parse_known_args()
print args, rest
while rest:
    args, rest = parser1.parse_known_args(rest)
    print args, rest

我将parser foo放在subp之前,因为它会减少混淆。最后的位置(bar)可能与其中一个子分析器或其中一个嵌套子分析器的参数混淆 - 尤其是在生成错误消息时。

要了解parse_args如何将参数字符串分配给各种位置,请尝试以下脚本:

parser = argparse.ArgumentParser()
parser.add_argument('foo')
parser.add_argument('cmd', nargs=argparse.PARSER, choices=['cmd1','cmd2']) 
parser.add_argument('bar') 
print parser.parse_args()

对于parser,subparsers参数看起来就像一个位置,至少需要一个字符串(类似'+'),第一个必须匹配choices。它将收到所有剩余的'字符串,符合其他位置的要求。