我觉得argparse中的sub_parsers有一个小小的限制,如果说,你有一套工具可能有类似的选项,可能在不同层次上传播。出现这种情况可能很少,但如果您正在编写可插拔/模块化代码,则可能会发生。
我有下面的例子。它是牵强和目前没有得到很好的解释,因为它是比较晚的,但这里有云:
Usage: tool [-y] {a, b}
a [-x] {create, delete}
create [-x]
delete [-y]
b [-y] {push, pull}
push [-x]
pull [-x]
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument('-x', action = 'store_true')
parser.add_argument('-y', action = 'store_true')
subparsers = parser.add_subparsers(dest = 'command')
parser_a = subparsers.add_parser('a')
parser_a.add_argument('-x', action = 'store_true')
subparsers_a = parser_a.add_subparsers(dest = 'sub_command')
parser_a_create = subparsers_a.add_parser('create')
parser_a_create.add_argument('-x', action = 'store_true')
parser_a_delete = subparsers_a.add_parser('delete')
parser_a_delete.add_argument('-y', action = 'store_true')
parser_b = subparsers.add_parser('b')
parser_b.add_argument('-y', action = 'store_true')
subparsers_b = parser_b.add_subparsers(dest = 'sub_command')
parser_b_create = subparsers_b.add_parser('push')
parser_b_create.add_argument('-x', action = 'store_true')
parser_b_delete = subparsers_b.add_parser('pull')
parser_b_delete.add_argument('-y', action = 'store_true')
print parser.parse_args(['-x', 'a', 'create'])
print parser.parse_args(['a', 'create', '-x'])
print parser.parse_args(['b', '-y', 'pull', '-y'])
print parser.parse_args(['-x', 'b', '-y', 'push', '-x'])
输出
Namespace(command='a', sub_command='create', x=True, y=False)
Namespace(command='a', sub_command='create', x=True, y=False)
Namespace(command='b', sub_command='pull', x=False, y=True)
Namespace(command='b', sub_command='push', x=True, y=True)
正如你所看到的,这是很难区分每个参数沿链设置的位置。 您可以通过更改每个变量的名称来解决此问题。例如,您可以将'dest'设置为'x','a_x','a_create_x','b_push_x'等,但这会很痛苦,很难分离出来。
另一种方法是让ArgumentParser在到达子命令后停止并将其余的参数传递给另一个独立的分析器,以便它可以生成单独的对象。 您可以尝试通过使用'parse_known_args()'而不是为每个子命令定义参数来实现。但是,这并不好,因为之前未解析的参数仍然存在,并可能会使程序混淆。
我觉得有点便宜,但有用的解决方法是让argparse将下列参数解释为列表中的字符串。这可以通过将前缀设置为空终止符'\ 0'(或其他'难以使用'的字符)来完成 - 如果前缀为空,那么代码会抛出一个错误,至少在Python 2.7中。 3。
实施例:
parser = ArgumentParser()
parser.add_argument('-x', action = 'store_true')
parser.add_argument('-y', action = 'store_true')
subparsers = parser.add_subparsers(dest = 'command')
parser_a = subparsers.add_parser('a' prefix_chars = '\0')
parser_a.add_argument('args', type = str, nargs = '*')
print parser.parse_args(['-xy', 'a', '-y', '12'])
输出:
Namespace(args=['-y', '12'], command='a', x=True, y=True)
注意,它不消耗第二-y
选项。 然后,您可以将结果'args'传递给另一个ArgumentParser。
缺点:
- 帮助可能不能很好地处理。将不得不采取更多的解决方法
- 遇到错误可能很难追踪,并需要一些额外的努力,以确保错误消息是正确链接。
- 与多个ArgumentParsers相关的一点额外开销。
如果有人对此有更多意见,请告诉我。
公司我工作的有那么使用argparse一个V2.6基线是,它必须被纳入作为外部库,仅在需要时加载的问题。远非不可能,只是不理想。至于cmdln库,给我一些我不希望重新创建的基本功能。这就是说我反对使用别的东西。 – tima 2011-12-16 19:27:30