如何向 argparse 子命令添加通用参数?
How to add common arguments to argparse subcommands?
使用 argparse 时,一些子命令需要相同的选项,我使用 parents
以避免在每个子命令中重复定义它们。
脚本文件名:testarg.py
import argparse
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('-H', '--host', default='192.168.122.1')
parser.add_argument('-P', '--port', default='12345')
subparsers = parser.add_subparsers()
# subcommand a
parser_a = subparsers.add_parser('a', parents=[parser])
parser_a.add_argument('-D', '--daemon', action='store_true')
parser_a.add_argument('-L', '--log', default='/tmp/test.log')
# subcommand b
parser_b = subparsers.add_parser('b', parents=[parser])
parser_b.add_argument('-D', '--daemon', action='store_true')
# subcommand c
parser_c = subparsers.add_parser('c', parents=[parser])
args = parser.parse_args()
print args
但是当我运行命令时:
>>>./testarg.py a
usage: testarg.py a [-h] [-H HOST] [-P PORT] [-D] [-L LOG] {a,b,c} ...
testarg.py a: error: too few arguments
期望输出:
>>>./testarg.py a
Namespace(daemon=False, host='192.168.122.1', log='/tmp/test.log', port='12345')
>>>./testarg.py b -H 127.0.0.1 -P 11111
Namespace(daemon=False, host='127.0.0.1', port='11111')
>>>./testarg.py c
Namespace(host='192.168.122.1', port='12345')
also,
>>>./testarg.py c -H 127.0.0.1 -P 12222
Namespace(host='127.0.0.1', port='12222')
我错过了什么?
制作一个单独的父解析器并将其传递给子解析器
import argparse
parent_parser = argparse.ArgumentParser(add_help=False)
parent_parser.add_argument('-H', '--host', default='192.168.122.1')
parent_parser.add_argument('-P', '--port', default='12345')
parser = argparse.ArgumentParser(add_help=False)
subparsers = parser.add_subparsers()
# subcommand a
parser_a = subparsers.add_parser('a', parents = [parent_parser])
parser_a.add_argument('-D', '--daemon', action='store_true')
parser_a.add_argument('-L', '--log', default='/tmp/test.log')
# subcommand b
parser_b = subparsers.add_parser('b', parents = [parent_parser])
parser_b.add_argument('-D', '--daemon', action='store_true')
# subcommand c
parser_c = subparsers.add_parser('c', parents = [parent_parser])
args = parser.parse_args()
print args
这给出了预期的结果
$ python arg.py a
Namespace(daemon=False, host='192.168.122.1', log='/tmp/test.log', port='12345')
$ python arg.py b -H 127.0.0.1 -P 11111
Namespace(daemon=False, host='127.0.0.1', port='11111')
$ python arg.py c
Namespace(host='192.168.122.1', port='12345')
当您使用 parser
本身作为子解析器的 parents
时,您递归地将 subparsers
添加到每个子解析器。 add_subparsers
命令实际上定义了一个位置参数,一个获取选择的参数,{'a','b','c'}
。它最终期望 prog.py a a a ...
,每个子解析器都期望另一个子解析器命令等
我从未见过有人尝试过这种定义,我想了想才意识到发生了什么。
@Alik's
方法是正确的。单独定义父解析器,不要直接使用。它只是您想要添加到每个子解析器的那些 -H
和 -P
操作的来源。这就是您想要添加到子解析器的所有内容。
另一种方法是在主解析器中简单地定义 -H
和 -P
。
parser = argparse.ArgumentParser()
parser.add_argument('-H', '--host', default='192.168.122.1')
parser.add_argument('-P', '--port', default='12345')
subparsers = parser.add_subparsers()
# subcommand a
parser_a = subparsers.add_parser('a')
parser_a.add_argument('-D', '--daemon', action='store_true')
....
它将以相同的方式运行,除了 -H
和 -P
必须在 subparser 命令之前指定。
0015:~/mypy$ python stack33645859.py -H 127.0.0.1 -P 1111 b
Namespace(daemon=False, host='127.0.0.1', port='1111')
它们仍然以相同的方式出现在命名空间中,只是命令行中的顺序不同。 help
也会不同
第三个选项是通过循环或函数以编程方式添加公共参数。一个粗略的例子是:
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
splist = []
for cmd in ['a','b','c']:
p = subparsers.add_parser(cmd)
p.add_argument('-H', '--host', default='192.168.122.1')
p.add_argument('-P', '--port', default='12345')
splist.append(p)
splist[0].add_argument('-D', '--daemon', action='store_true')
在功能上它与 @Alik's
方法类似,但有细微差别。使用 parent
,仅创建一对 H
和 P
操作对象。将引用添加到每个子解析器。
对于我的,每个子解析器都有自己的 H
和 P
Action 对象。每个子解析器可以为这些参数定义不同的 defaults
。我记得这是另一个 SO 问题中的一个问题。
编码工作在所有情况下都是相似的。
使用 argparse 时,一些子命令需要相同的选项,我使用 parents
以避免在每个子命令中重复定义它们。
脚本文件名:testarg.py
import argparse
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('-H', '--host', default='192.168.122.1')
parser.add_argument('-P', '--port', default='12345')
subparsers = parser.add_subparsers()
# subcommand a
parser_a = subparsers.add_parser('a', parents=[parser])
parser_a.add_argument('-D', '--daemon', action='store_true')
parser_a.add_argument('-L', '--log', default='/tmp/test.log')
# subcommand b
parser_b = subparsers.add_parser('b', parents=[parser])
parser_b.add_argument('-D', '--daemon', action='store_true')
# subcommand c
parser_c = subparsers.add_parser('c', parents=[parser])
args = parser.parse_args()
print args
但是当我运行命令时:
>>>./testarg.py a
usage: testarg.py a [-h] [-H HOST] [-P PORT] [-D] [-L LOG] {a,b,c} ...
testarg.py a: error: too few arguments
期望输出:
>>>./testarg.py a
Namespace(daemon=False, host='192.168.122.1', log='/tmp/test.log', port='12345')
>>>./testarg.py b -H 127.0.0.1 -P 11111
Namespace(daemon=False, host='127.0.0.1', port='11111')
>>>./testarg.py c
Namespace(host='192.168.122.1', port='12345')
also,
>>>./testarg.py c -H 127.0.0.1 -P 12222
Namespace(host='127.0.0.1', port='12222')
我错过了什么?
制作一个单独的父解析器并将其传递给子解析器
import argparse
parent_parser = argparse.ArgumentParser(add_help=False)
parent_parser.add_argument('-H', '--host', default='192.168.122.1')
parent_parser.add_argument('-P', '--port', default='12345')
parser = argparse.ArgumentParser(add_help=False)
subparsers = parser.add_subparsers()
# subcommand a
parser_a = subparsers.add_parser('a', parents = [parent_parser])
parser_a.add_argument('-D', '--daemon', action='store_true')
parser_a.add_argument('-L', '--log', default='/tmp/test.log')
# subcommand b
parser_b = subparsers.add_parser('b', parents = [parent_parser])
parser_b.add_argument('-D', '--daemon', action='store_true')
# subcommand c
parser_c = subparsers.add_parser('c', parents = [parent_parser])
args = parser.parse_args()
print args
这给出了预期的结果
$ python arg.py a
Namespace(daemon=False, host='192.168.122.1', log='/tmp/test.log', port='12345')
$ python arg.py b -H 127.0.0.1 -P 11111
Namespace(daemon=False, host='127.0.0.1', port='11111')
$ python arg.py c
Namespace(host='192.168.122.1', port='12345')
当您使用 parser
本身作为子解析器的 parents
时,您递归地将 subparsers
添加到每个子解析器。 add_subparsers
命令实际上定义了一个位置参数,一个获取选择的参数,{'a','b','c'}
。它最终期望 prog.py a a a ...
,每个子解析器都期望另一个子解析器命令等
我从未见过有人尝试过这种定义,我想了想才意识到发生了什么。
@Alik's
方法是正确的。单独定义父解析器,不要直接使用。它只是您想要添加到每个子解析器的那些 -H
和 -P
操作的来源。这就是您想要添加到子解析器的所有内容。
另一种方法是在主解析器中简单地定义 -H
和 -P
。
parser = argparse.ArgumentParser()
parser.add_argument('-H', '--host', default='192.168.122.1')
parser.add_argument('-P', '--port', default='12345')
subparsers = parser.add_subparsers()
# subcommand a
parser_a = subparsers.add_parser('a')
parser_a.add_argument('-D', '--daemon', action='store_true')
....
它将以相同的方式运行,除了 -H
和 -P
必须在 subparser 命令之前指定。
0015:~/mypy$ python stack33645859.py -H 127.0.0.1 -P 1111 b
Namespace(daemon=False, host='127.0.0.1', port='1111')
它们仍然以相同的方式出现在命名空间中,只是命令行中的顺序不同。 help
也会不同
第三个选项是通过循环或函数以编程方式添加公共参数。一个粗略的例子是:
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
splist = []
for cmd in ['a','b','c']:
p = subparsers.add_parser(cmd)
p.add_argument('-H', '--host', default='192.168.122.1')
p.add_argument('-P', '--port', default='12345')
splist.append(p)
splist[0].add_argument('-D', '--daemon', action='store_true')
在功能上它与 @Alik's
方法类似,但有细微差别。使用 parent
,仅创建一对 H
和 P
操作对象。将引用添加到每个子解析器。
对于我的,每个子解析器都有自己的 H
和 P
Action 对象。每个子解析器可以为这些参数定义不同的 defaults
。我记得这是另一个 SO 问题中的一个问题。
编码工作在所有情况下都是相似的。