调度 Python 的 argparse 子命令的最佳方式
Best manner of dispatching Python's argparse subcommands
我正在研究 Python 的 argparse
模块以获得相当复杂和庞大的子命令结构。到目前为止,参数解析非常顺利,一切正常,但我正在寻找一种更好的方法来管理子命令的执行方式。
这是我的 dummy/playaround 应用程序的示例:
def a_func(cmd_args):
print(cmd_args)
def b_func(cmd_args):
print(cmd_args)
CMD_DISPATCHER = {
'a': a_func,
'b': b_func
}
def parse_commands():
# Create top-level parser
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='subcmd_name')
# Create parser for the "a" sub-command
parser_a = subparsers.add_parser('a')
parser_a.add_argument('-bar', type=int)
# Create parser for the "b" sub-command
parser_b = subparsers.add_parser('b')
parser_b.add_argument('-foo', type=int)
args = parser.parse_args()
CMD_DISPATCHER[args.subcmd_name](args)
def main():
parse_commands()
if __name__ == '__main__':
main()
如您所见,我在这里使用一个简单的 dict
(CMD_DISPATCHER
) 作为将子命令名称与其功能相关联的映射。
正如我所说,这只是我想要实现的一个简单示例,但实际项目会有许多嵌套的子命令,所以我想要一种更好的方法来管理这几个子命令。
你知道 better/more-professional 的方法吗?
好的,经过更多的研究,我找到了一个适合我需要的好方法:set_defaults
。我之前使用过这个函数,但总是设置默认的现有默认参数值。我没有注意到 argparse documentation 提供的清晰示例:
>>> # sub-command functions
>>> def foo(args):
... print(args.x * args.y)
...
>>> def bar(args):
... print('((%s))' % args.z)
...
>>> # create the top-level parser
>>> parser = argparse.ArgumentParser()
>>> subparsers = parser.add_subparsers()
>>>
>>> # create the parser for the "foo" command
>>> parser_foo = subparsers.add_parser('foo')
>>> parser_foo.add_argument('-x', type=int, default=1)
>>> parser_foo.add_argument('y', type=float)
>>> parser_foo.set_defaults(func=foo)
>>>
>>> # create the parser for the "bar" command
>>> parser_bar = subparsers.add_parser('bar')
>>> parser_bar.add_argument('z')
>>> parser_bar.set_defaults(func=bar)
>>>
>>> # parse the args and call whatever function was selected
>>> args = parser.parse_args('foo 1 -x 2'.split())
>>> args.func(args)
2.0
>>>
>>> # parse the args and call whatever function was selected
>>> args = parser.parse_args('bar XYZYX'.split())
>>> args.func(args)
((XYZYX))
如您所见,行 parser_bar.set_defaults(func=bar)
将新变量设置为 parser_bar
个参数。在这种情况下 bar
是一个函数,最终用作行 args.func(args)
.
中的子命令执行器
我希望这对以后的人有所帮助。
我正在研究 Python 的 argparse
模块以获得相当复杂和庞大的子命令结构。到目前为止,参数解析非常顺利,一切正常,但我正在寻找一种更好的方法来管理子命令的执行方式。
这是我的 dummy/playaround 应用程序的示例:
def a_func(cmd_args):
print(cmd_args)
def b_func(cmd_args):
print(cmd_args)
CMD_DISPATCHER = {
'a': a_func,
'b': b_func
}
def parse_commands():
# Create top-level parser
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='subcmd_name')
# Create parser for the "a" sub-command
parser_a = subparsers.add_parser('a')
parser_a.add_argument('-bar', type=int)
# Create parser for the "b" sub-command
parser_b = subparsers.add_parser('b')
parser_b.add_argument('-foo', type=int)
args = parser.parse_args()
CMD_DISPATCHER[args.subcmd_name](args)
def main():
parse_commands()
if __name__ == '__main__':
main()
如您所见,我在这里使用一个简单的 dict
(CMD_DISPATCHER
) 作为将子命令名称与其功能相关联的映射。
正如我所说,这只是我想要实现的一个简单示例,但实际项目会有许多嵌套的子命令,所以我想要一种更好的方法来管理这几个子命令。
你知道 better/more-professional 的方法吗?
好的,经过更多的研究,我找到了一个适合我需要的好方法:set_defaults
。我之前使用过这个函数,但总是设置默认的现有默认参数值。我没有注意到 argparse documentation 提供的清晰示例:
>>> # sub-command functions
>>> def foo(args):
... print(args.x * args.y)
...
>>> def bar(args):
... print('((%s))' % args.z)
...
>>> # create the top-level parser
>>> parser = argparse.ArgumentParser()
>>> subparsers = parser.add_subparsers()
>>>
>>> # create the parser for the "foo" command
>>> parser_foo = subparsers.add_parser('foo')
>>> parser_foo.add_argument('-x', type=int, default=1)
>>> parser_foo.add_argument('y', type=float)
>>> parser_foo.set_defaults(func=foo)
>>>
>>> # create the parser for the "bar" command
>>> parser_bar = subparsers.add_parser('bar')
>>> parser_bar.add_argument('z')
>>> parser_bar.set_defaults(func=bar)
>>>
>>> # parse the args and call whatever function was selected
>>> args = parser.parse_args('foo 1 -x 2'.split())
>>> args.func(args)
2.0
>>>
>>> # parse the args and call whatever function was selected
>>> args = parser.parse_args('bar XYZYX'.split())
>>> args.func(args)
((XYZYX))
如您所见,行 parser_bar.set_defaults(func=bar)
将新变量设置为 parser_bar
个参数。在这种情况下 bar
是一个函数,最终用作行 args.func(args)
.
我希望这对以后的人有所帮助。