我希望能够使用argparse.ArgumentParser对象中的全局选项来覆盖/扩充子命令的默认值。
一个例子是显示的帮助反映了全局更新,即以下玩具示例:
import argparse
import os
import sys
# Global parser and options.
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("--user",
dest="user",
default=os.environ.get("USER"),
help="Override the setting of the $USER variable.")
# Sub-command parser and options.
subparsers = parser.add_subparsers()
command = subparsers.add_parser(
"command",
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
command.add_argument("--config",
dest="config",
default="~%s/config" % os.environ.get("USER"),
help="The config file.")
options = parser.parse_args()
理想情况下,当我在帮助模式下运行时,我会得到,
> python example.py --user thing command --help
usage: example.py command [-h] [--config CONFIG]
optional arguments:
-h, --help show this help message and exit
--config CONFIG The config file. (default: ~thing/config)
即,配置文件路径是用户特定的(事物)。我意识到我可以将默认配置更改为"~%(user)s/config"
,然后在运行时使用options命名空间解决此问题,但我希望帮助更明确。
我收集一个替代解决方案是尝试解析一次参数以获得全局选项,即
if "--help" in sys.argv:
# Parse the command minus the help to obtain the global options.
args = sys.argv[1:]
args.remove("--help")
# Update the defaults with the global options.
options = parser.parse_args(args)
command.set_defaults(config="~%s/config" % options.user)
# Re-parse the options.
parser.parse_args()
虽然这看起来有点哈哈。有更好的方法/解决方案吗?
答案 0 :(得分:4)
在定义全局选项之后,但在定义子命令之前,请调用parse_known_args
以找出--user
的值。然后,使用--user
的值定义子分析器命令,以定义默认值--config
,之后
调用parse_args
来解析命令行上的所有选项。
这与您的替代方案略有不同,但它将所有命令行处理保留在argparse
对象中。
(为了缩短这个答案,我稍微减少了你的代码。)
import os
import argparse
# Global preparser and options.
preparser = argparse.ArgumentParser(add_help=False)
preparser.add_argument("--user", dest="user", default=os.environ.get("USER"))
# ****** NEW *******
options, _ = preparser.parse_known_args() # Ignore what we haven't defined yet
user = options.user # Use this to define the default of --config
parser = argparse.ArgumentParser(parents=[ preparser ], add_help=True,
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
# Sub-command parser and options.
subparsers = parser.add_subparsers()
command = subparsers.add_parser("command")
# ****** MODIFIED *******
command.add_argument("--config", dest="config", default="~%s/config" % (user,))
options = parser.parse_args()
答案 1 :(得分:0)
这是一个在运行时直接修改帮助行的解决方案。它也可以修改os.environ
或其他一些全局,但我会保持简单。关键是将add_argument('--config'...)
创建的操作分配给变量。 help
只是该变量的一个属性。您可以自由修改它。
class FooAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
config.help = 'new user (%s)'% values
setattr(namespace, self.dest, values)
parser = argparse.ArgumentParser()
parser.add_argument('--user',action=FooAction)
sub = parser.add_subparsers()
cmd = sub.add_parser('cmd')
config = cmd.add_argument('--config',help='initial help')
config.help = 'default help' # alt way of setting 'help'
# print config # to see other attributes of the config action
args = parser.parse_args()
print args
仅使用cmd -h
调用,我们得到default help
$ python stack12167228.py cmd -h
usage: stack12167228.py cmd [-h] [--config CONFIG]
optional arguments:
-h, --help show this help message and exit
--config CONFIG default help
使用--user xxx cmd -h
调用,自定义帮助
$ python stack12167228.py --user xxx cmd -h
usage: stack12167228.py cmd [-h] [--config CONFIG]
optional arguments:
-h, --help show this help message and exit
--config CONFIG new user (xxx)