Python argparse,根据父参数值提供不同的参数
Python argparse, provide different arguments based on parent argument value
这是我想做的事情:
看起来像 git 命令行为的命令。无论您输入 git commit 还是 git checkout,您都不会获得相同的选项。
但就我而言,我想根据参数值(文件名)提供不同的参数,如下所示:
>cmd file.a -h
usage: cmd filename [-opt1] [-opt2]
positional arguments:
filename file to process
optional arguments:
-opt1 do something on files of type 'a'
-opt2 do something else on files of type 'a'
>cmd file.b -h
usage: cmd filename [-opt3] [-opt4]
positional arguments:
filename file to process
optional arguments:
-opt3 do something on files of type 'b'
-opt4 do something else on files of type 'b'
是否可以使用 python 和 argparse 做这种事情?
到目前为止我尝试过的是:
parser = argparse.Argument_parser(prog='cmd')
subparsers = parser.add_subparsers()
parser.add_argument('filename',
help="file or sequence to process")
args = parser.parse_args(args=argv[1:])
sub_parser = subparsers.add_parser(args.filename, help="job type")
base, ext = os.path.splitext(args.filename)
if ext == 'a':
sub_parser.add_argument("-opt1", action='store_true')
sub_parser.add_argument("-opt2", action='store_true')
elif ext == 'b':
sub_parser.add_argument("-opt3", action='store_true')
sub_parser.add_argument("-opt4", action='store_true')
args = parser.parse_args(args=argv[1:])
我不知道我是否应该使用子解析器或子解析器或组,我有点迷失在 argparse
提供的所有可能性中
当你查看 parse_args()
implementation 时,你会注意到它一次解析所有参数(它不使用 yield
来连续生成状态)所以你必须准备你的结构之前和之后的一半参数将被解析。
Taking from official example in the docs 你应该在开始解析之前添加子解析器,如下所示:
import argparse
parser = argparse.ArgumentParser(prog='PROG')
subparsers = parser.add_subparsers(help='sub-command help')
# create the parser for the "a" command
parser_a = subparsers.add_parser('a', help='a help')
parser_a.add_argument("--opt1", action='store_true')
parser_a.add_argument("--opt2", action='store_true')
# create the parser for the "b" command
parser_b = subparsers.add_parser('b', help='b help')
parser_b.add_argument("--opt3", action='store_true')
parser_b.add_argument("--opt4", action='store_true')
# parse some argument lists
print(parser.parse_args())
并且输出(在命令行中)帮助很好地打印:
D:\tmp>s.py -h
usage: PROG [-h] {a,b} ...
positional arguments:
{a,b} sub-command help
a a help
b b help
optional arguments:
-h, --help show this help message and exit
A 个参数被解析
D:\tmp>s.py a --opt1
Namespace(opt1=True, opt2=False)
B 个参数被解析
D:\tmp>s.py b
Namespace(opt3=False, opt4=False)
还有参数:
D:\tmp>s.py b --opt3
Namespace(opt3=True, opt4=False)
运行 A B 中的参数导致错误:
D:\tmp>s.py b --opt2
usage: PROG [-h] {a,b} ...
PROG: error: unrecognized arguments: --opt2
此外,如果您需要使用 identify which subparser,您可以将 dest=name
添加到 parser.add_subparsers()
调用(我认为文档中没有正确强调这一点):
subparsers = parser.add_subparsers(help='sub-command help', dest='subparser_name')
结果为:
D:\tmp>s.py b --opt3
Namespace(opt3=True, opt4=False, subparser_name='b')
如果您确实需要动态创建参数(例如从 expensive 资源加载一些参数选项),您可以使用 parse_known_args()
:
Sometimes a script may only parse a few of the command-line arguments, passing the remaining arguments on to another script or program. In these cases, the parse_known_args()
method can be useful. It works much like parse_args()
except that it does not produce an error when extra arguments are present. Instead, it returns a two item tuple containing the populated namespace and the list of remaining argument strings.
毕竟,parse_args()
只是检查尾随参数:
def parse_args(self, args=None, namespace=None):
args, argv = self.parse_known_args(args, namespace)
if argv:
msg = _('unrecognized arguments: %s')
self.error(msg % ' '.join(argv))
return args
然后你可以在 argv
上重新执行另一个解析器,但我可以想象这会带来一些问题,我不会推荐它,直到 真的 必要。
这是我想做的事情: 看起来像 git 命令行为的命令。无论您输入 git commit 还是 git checkout,您都不会获得相同的选项。 但就我而言,我想根据参数值(文件名)提供不同的参数,如下所示:
>cmd file.a -h
usage: cmd filename [-opt1] [-opt2]
positional arguments:
filename file to process
optional arguments:
-opt1 do something on files of type 'a'
-opt2 do something else on files of type 'a'
>cmd file.b -h
usage: cmd filename [-opt3] [-opt4]
positional arguments:
filename file to process
optional arguments:
-opt3 do something on files of type 'b'
-opt4 do something else on files of type 'b'
是否可以使用 python 和 argparse 做这种事情?
到目前为止我尝试过的是:
parser = argparse.Argument_parser(prog='cmd')
subparsers = parser.add_subparsers()
parser.add_argument('filename',
help="file or sequence to process")
args = parser.parse_args(args=argv[1:])
sub_parser = subparsers.add_parser(args.filename, help="job type")
base, ext = os.path.splitext(args.filename)
if ext == 'a':
sub_parser.add_argument("-opt1", action='store_true')
sub_parser.add_argument("-opt2", action='store_true')
elif ext == 'b':
sub_parser.add_argument("-opt3", action='store_true')
sub_parser.add_argument("-opt4", action='store_true')
args = parser.parse_args(args=argv[1:])
我不知道我是否应该使用子解析器或子解析器或组,我有点迷失在 argparse
提供的所有可能性中当你查看 parse_args()
implementation 时,你会注意到它一次解析所有参数(它不使用 yield
来连续生成状态)所以你必须准备你的结构之前和之后的一半参数将被解析。
Taking from official example in the docs 你应该在开始解析之前添加子解析器,如下所示:
import argparse
parser = argparse.ArgumentParser(prog='PROG')
subparsers = parser.add_subparsers(help='sub-command help')
# create the parser for the "a" command
parser_a = subparsers.add_parser('a', help='a help')
parser_a.add_argument("--opt1", action='store_true')
parser_a.add_argument("--opt2", action='store_true')
# create the parser for the "b" command
parser_b = subparsers.add_parser('b', help='b help')
parser_b.add_argument("--opt3", action='store_true')
parser_b.add_argument("--opt4", action='store_true')
# parse some argument lists
print(parser.parse_args())
并且输出(在命令行中)帮助很好地打印:
D:\tmp>s.py -h
usage: PROG [-h] {a,b} ...
positional arguments:
{a,b} sub-command help
a a help
b b help
optional arguments:
-h, --help show this help message and exit
A 个参数被解析
D:\tmp>s.py a --opt1
Namespace(opt1=True, opt2=False)
B 个参数被解析
D:\tmp>s.py b
Namespace(opt3=False, opt4=False)
还有参数:
D:\tmp>s.py b --opt3
Namespace(opt3=True, opt4=False)
运行 A B 中的参数导致错误:
D:\tmp>s.py b --opt2
usage: PROG [-h] {a,b} ...
PROG: error: unrecognized arguments: --opt2
此外,如果您需要使用 identify which subparser,您可以将 dest=name
添加到 parser.add_subparsers()
调用(我认为文档中没有正确强调这一点):
subparsers = parser.add_subparsers(help='sub-command help', dest='subparser_name')
结果为:
D:\tmp>s.py b --opt3
Namespace(opt3=True, opt4=False, subparser_name='b')
如果您确实需要动态创建参数(例如从 expensive 资源加载一些参数选项),您可以使用 parse_known_args()
:
Sometimes a script may only parse a few of the command-line arguments, passing the remaining arguments on to another script or program. In these cases, the
parse_known_args()
method can be useful. It works much likeparse_args()
except that it does not produce an error when extra arguments are present. Instead, it returns a two item tuple containing the populated namespace and the list of remaining argument strings.
毕竟,parse_args()
只是检查尾随参数:
def parse_args(self, args=None, namespace=None):
args, argv = self.parse_known_args(args, namespace)
if argv:
msg = _('unrecognized arguments: %s')
self.error(msg % ' '.join(argv))
return args
然后你可以在 argv
上重新执行另一个解析器,但我可以想象这会带来一些问题,我不会推荐它,直到 真的 必要。