支持 argparse 中子命令之前或之后的全局参数

问题描述 投票:0回答:3

使用解析器设置

parents
参数将允许在解析器之间共享公共参数(例如父命令和子命令)。但是,当使用使用 dest
 关键字指定 value 属性的参数时,将基本解析器应用于父命令和子命令似乎会用子命令解析器的值覆盖父解析器的值,调用是否在子命令中指定了参数。

如何使用

argparse

 module
合并父命令和子命令中的选项(即,如果任一解析器包含该选项,则存储值,如果两个解析器都没有指定该选项,则使用默认值,并且它不如果两个解析器都指定了选项,如何处理)?

sample.py

from argparse import ArgumentParser parser = ArgumentParser(add_help=False) # The "base" parser.add_argument('-v', '--verbose', dest='verbose', action='store_true') parser.add_argument('-d', '--dir', dest='dir', default=None) parser_main = ArgumentParser(parents=[parser]) subparsers = parser_main.add_subparsers(dest='command') subparsers.add_parser('cmd1', parents=[parser]) args = parser_main.parse_args() print(str(args))
然后,在 shell 中:

> sample.py -v -d abc Namespace(command=None, dir='abc', verbose=True) > sample.py -v cmd1 -d abc Namespace(command='cmd1', dir='abc', verbose=False) > sample.py -d abc cmd1 -v Namespace(command='cmd1', dir=None, verbose=True) > sample.py cmd1 -v -d abc Namespace(command='cmd1', dir='abc', verbose=True)
    
python argparse
3个回答
3
投票
使用

SUPPRESS

 作为子解析器默认值可防止其覆盖父解析器值。  在解析开始时, 
SUPPRESS
 默认值不会插入到 
namespace
 中。  仅当用户使用该参数时才会写入值。

import argparse parser = argparse.ArgumentParser() parser.add_argument('-f', '--foo', default='foobar') parser.add_argument('-v', '--verbose', action='store_const', default=False, const=True) sp = parser.add_subparsers(dest='cmd') sp1 = sp.add_parser('cmd1') sp1.add_argument('-f', '--foo', default=argparse.SUPPRESS) sp1.add_argument('-v', '--verbose', action='store_const', default=argparse.SUPPRESS, const=True) args = parser.parse_args() print(args)
样本运行:

1833:~/mypy$ python3 stack62904585.py Namespace(cmd=None, foo='foobar', verbose=False) 1834:~/mypy$ python3 stack62904585.py --foo FOO -v Namespace(cmd=None, foo='FOO', verbose=True) 1834:~/mypy$ python3 stack62904585.py cmd1 Namespace(cmd='cmd1', foo='foobar', verbose=False) 1834:~/mypy$ python3 stack62904585.py -v cmd1 -f bar Namespace(cmd='cmd1', foo='bar', verbose=True)
最后改变此行为的补丁(2014)

https://bugs.python.org/issue9351 子命令上的 argparse set_defaults 应覆盖顶级 set_defaults

还有

https://bugs.python.org/issue27859


0
投票
您可以通过使用

dest

 关键字指定不同的名称来将值存储在不同的属性中:

from argparse import ArgumentParser parser = ArgumentParser(add_help=False) # The "base" parser.add_argument('-v', '--verbose', dest='verbose', action='store_true') parser.add_argument('-d', '--dir', dest='dir', default=None) parser_main = ArgumentParser() parser_main.add_argument('-v', '--verbose', dest='g_verbose', action='store_true') parser_main.add_argument('-d', '--dir', dest='g_dir', default=None) subparsers = parser_main.add_subparsers(dest='command') subparsers.add_parser('cmd1', parents=[parser]) args = parser_main.parse_args() verbose = args.verbose or args.g_verbose if hasattr(args, 'verbose') else args.g_verbose d = (args.g_dir if args.dir is None else args.dir) if hasattr(args, 'dir') else args.g_dir
    

0
投票
有一种优雅的方法可以做到这一点,不需要重复代码或其他技巧。分两遍解析参数。首先,使用

parse_known_args()

 的通用参数,然后是在第一遍生成的命名空间中传递的所有其他参数。

from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument('-v', '--verbose', dest='verbose', action='store_true') parser.add_argument('-d', '--dir', dest='dir', default=None) parser_main = ArgumentParser() subparsers = parser_main.add_subparsers(dest='command') subparsers.add_parser('cmd1') args,remaining_args = parser.parse_known_args() parser_main.parse_args(remaining_args, namespace=args) print(str(args))
    
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.