Python argparse 覆盖来自父级的帮助
Python argparse override help from parent
我有一个我正在构建的 CLI,它利用子命令的子解析器类似于 git 等工具。我的一些子命令共享公共选项,因此我有一个定义选项的组解析器,每个需要它们的子命令都使用 parents=group_parser
作为参数之一。例如:
group_parser = argparse.ArgumentParser()
group_parser.add_argument('-f', '--foo', action='store_true')
command1_parser = subparsers.add_parser('command1', parents=[group_parser])
command2_parser = subparsers.add_parser('command2', parents=[group_parser])
因此,如您所见,command1 和 command2 都继承了选项 --foo
。我想要做的是在 command1 和 command2 上分别更新 foo 的帮助文本。例如,如果我 运行 myprog command1 -h
,我希望它为 --foo
说一条与我 运行 myprog command2 -h
不同的帮助信息。问题是在我执行 parse_args()
之前没有要为该参数更新的名称空间,所以这样的事情不起作用:
group_parser = argparse.ArgumentParser()
group_parser.add_argument('-f', '--foo', action='store_true')
command1_parser = subparsers.add_parser('command1', parents=[group_parser])
command1.foo['help'] = "foo help for command1"
command2_parser = subparsers.add_parser('command2', parents=[group_parser])
command2.foo['help'] = "foo help for command2"
是否可以通过某种方式向 add_argument()
函数之外的参数添加额外的参数?唯一的其他解决方案是不使用继承的父级,只为每个子命令单独定义 foo,但如果有更新参数的方法,那将是理想的。
有一种方法可以在创建动作(参数)后更改 help
(和其他动作属性)。但是使用 parents
机制还有另一个问题——动作是通过引用复制的。因此,即使您可以为 command1
更改 help
,您最终也会为 command2
更改它。我在尝试更改 default
.
等属性时遇到过这种情况
我会添加一个插图,可能是对之前讨论的 link。
In [2]: parent = argparse.ArgumentParser(add_help=False)
In [4]: fooObj = parent.add_argument('--foo',default='foo1', help='foo help')
fooObj
是对此 add_argument
创建的 Action 的引用。
In [5]: fooObj.default
Out[5]: 'foo1'
In [6]: fooObj.help # the help parameter
Out[6]: 'foo help'
In [7]: parent.print_help()
usage: ipython3 [--foo FOO]
optional arguments:
--foo FOO foo help
更改帮助属性:
In [8]: fooObj.help = 'new help'
In [9]: parent.print_help()
usage: ipython3 [--foo FOO]
optional arguments:
--foo FOO new help
现在制作解析器和子解析器
In [10]: parser = argparse.ArgumentParser()
In [11]: sp = parser.add_subparsers()
In [13]: cmd1 = sp.add_parser('cmd1',parents=[parent])
In [14]: cmd2 = sp.add_parser('cmd2',parents=[parent])
In [15]: cmd2.print_help()
usage: ipython3 cmd2 [-h] [--foo FOO]
optional arguments:
-h, --help show this help message and exit
--foo FOO new help
_actions
是为解析器定义的参数列表:
In [16]: cmd1._actions
Out[16]:
[_HelpAction(option_strings=['-h', '--help'], dest='help', nargs=0, const=None, default='==SUPPRESS==', type=None, choices=None, help='show this help message and exit', metavar=None),
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default='foo1', type=None, choices=None, help='new help', metavar=None)]
对比ids我们可以看出2d的动作和fooObj
是一样的。与 cmd2
.
相同
In [17]: id(cmd1._actions[1])
Out[17]: 2885458060
In [18]: id(fooObj)
Out[18]: 2885458060
更改 cmd1
的 help
也会更改 cmd2
In [19]: cmd1._actions[1].help = 'cmd1 foo'
In [20]: cmd2.print_help()
usage: ipython3 cmd2 [-h] [--foo FOO]
optional arguments:
-h, --help show this help message and exit
--foo FOO cmd1 foo
In [21]: fooObj.help
Out[21]: 'cmd1 foo'
这是一个尝试为子解析器提供不同默认值的案例:
argparse - Combining parent parser, subparsers and default values
最好使用您自己的实用函数将公共参数添加到子解析器。这样每个子解析器都可以拥有自己的 Action 对象副本,而不是共享它们。我认为 parents
机制在理论上比在实践中更好。
我有一个我正在构建的 CLI,它利用子命令的子解析器类似于 git 等工具。我的一些子命令共享公共选项,因此我有一个定义选项的组解析器,每个需要它们的子命令都使用 parents=group_parser
作为参数之一。例如:
group_parser = argparse.ArgumentParser()
group_parser.add_argument('-f', '--foo', action='store_true')
command1_parser = subparsers.add_parser('command1', parents=[group_parser])
command2_parser = subparsers.add_parser('command2', parents=[group_parser])
因此,如您所见,command1 和 command2 都继承了选项 --foo
。我想要做的是在 command1 和 command2 上分别更新 foo 的帮助文本。例如,如果我 运行 myprog command1 -h
,我希望它为 --foo
说一条与我 运行 myprog command2 -h
不同的帮助信息。问题是在我执行 parse_args()
之前没有要为该参数更新的名称空间,所以这样的事情不起作用:
group_parser = argparse.ArgumentParser()
group_parser.add_argument('-f', '--foo', action='store_true')
command1_parser = subparsers.add_parser('command1', parents=[group_parser])
command1.foo['help'] = "foo help for command1"
command2_parser = subparsers.add_parser('command2', parents=[group_parser])
command2.foo['help'] = "foo help for command2"
是否可以通过某种方式向 add_argument()
函数之外的参数添加额外的参数?唯一的其他解决方案是不使用继承的父级,只为每个子命令单独定义 foo,但如果有更新参数的方法,那将是理想的。
有一种方法可以在创建动作(参数)后更改 help
(和其他动作属性)。但是使用 parents
机制还有另一个问题——动作是通过引用复制的。因此,即使您可以为 command1
更改 help
,您最终也会为 command2
更改它。我在尝试更改 default
.
我会添加一个插图,可能是对之前讨论的 link。
In [2]: parent = argparse.ArgumentParser(add_help=False)
In [4]: fooObj = parent.add_argument('--foo',default='foo1', help='foo help')
fooObj
是对此 add_argument
创建的 Action 的引用。
In [5]: fooObj.default
Out[5]: 'foo1'
In [6]: fooObj.help # the help parameter
Out[6]: 'foo help'
In [7]: parent.print_help()
usage: ipython3 [--foo FOO]
optional arguments:
--foo FOO foo help
更改帮助属性:
In [8]: fooObj.help = 'new help'
In [9]: parent.print_help()
usage: ipython3 [--foo FOO]
optional arguments:
--foo FOO new help
现在制作解析器和子解析器
In [10]: parser = argparse.ArgumentParser()
In [11]: sp = parser.add_subparsers()
In [13]: cmd1 = sp.add_parser('cmd1',parents=[parent])
In [14]: cmd2 = sp.add_parser('cmd2',parents=[parent])
In [15]: cmd2.print_help()
usage: ipython3 cmd2 [-h] [--foo FOO]
optional arguments:
-h, --help show this help message and exit
--foo FOO new help
_actions
是为解析器定义的参数列表:
In [16]: cmd1._actions
Out[16]:
[_HelpAction(option_strings=['-h', '--help'], dest='help', nargs=0, const=None, default='==SUPPRESS==', type=None, choices=None, help='show this help message and exit', metavar=None),
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default='foo1', type=None, choices=None, help='new help', metavar=None)]
对比ids我们可以看出2d的动作和fooObj
是一样的。与 cmd2
.
In [17]: id(cmd1._actions[1])
Out[17]: 2885458060
In [18]: id(fooObj)
Out[18]: 2885458060
更改 cmd1
的 help
也会更改 cmd2
In [19]: cmd1._actions[1].help = 'cmd1 foo'
In [20]: cmd2.print_help()
usage: ipython3 cmd2 [-h] [--foo FOO]
optional arguments:
-h, --help show this help message and exit
--foo FOO cmd1 foo
In [21]: fooObj.help
Out[21]: 'cmd1 foo'
这是一个尝试为子解析器提供不同默认值的案例:
argparse - Combining parent parser, subparsers and default values
最好使用您自己的实用函数将公共参数添加到子解析器。这样每个子解析器都可以拥有自己的 Action 对象副本,而不是共享它们。我认为 parents
机制在理论上比在实践中更好。