我已经阅读了很多关于如何定义,解析和运行多个子运算符的问题和答案,如
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)
但是,这个实现有一个问题:参数input
和output
是为主解析器定义的,应该只使用一次。但是,每次调用parser.parse_known_args(rest)
都需要设置值,然后将其从rest
中删除。
这意味着第一次调用parse_known_args
会检索值,并且由于缺少参数,每次后续调用都会失败。
有没有解决方法可以解决这个问题,而无需手动将值复制到rest
列表中?
答案 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
。它将收到所有剩余的'字符串,符合其他位置的要求。