使用子解析器时,命令行参数被默认值覆盖

Posted

技术标签:

【中文标题】使用子解析器时,命令行参数被默认值覆盖【英文标题】:Command-line argument overwritten by default value when using subparser 【发布时间】:2019-09-09 06:31:40 【问题描述】:

我有一个带有子命令的程序,但它们都有共同的参数(例如,它们都需要输入和输出目录),我将它们包含在父解析器中以避免冗余。但是,我希望每个子命令具有不同的默认值,但这会导致命令行中提供的值被忽略。

MWE:

import argparse

top_parser = argparse.ArgumentParser()
top_parser.add_argument("--input-dir", type=str)

subparsers = top_parser.add_subparsers()

generate_parser = subparsers.add_parser("generate")
generate_parser.set_defaults(input_dir=".")

process_parser = subparsers.add_parser("process")
process_parser.set_defaults(input_dir="SOME_OTHER_DIR")

generate_args = top_parser.parse_args("--input-dir USE_THIS_DIR generate".split())
print("generate_args = ", generate_args)

process_args = top_parser.parse_args("--input-dir USE_THIS_DIR process".split())
print("process_args = ", process_args)

这给出了:

generate_args =  Namespace(input_dir='.')
process_args =  Namespace(input_dir='SOME_OTHER_DIR')

但我想要:

generate_args =  Namespace(input_dir='USE_THIS_DIR')
process_args =  Namespace(input_dir='USE_THIS_DIR')

我可以通过分别向每个子解析器添加参数来规避这种情况,但如果可能的话,我想避免这种冗余。

【问题讨论】:

几年前对argparse 的更改使子解析器的默认值覆盖了主解析器的默认值和/或值。找出其他方法,可能在后解析中,设置自定义默认值(例如,如果该值是默认默认值None)。 或者在设置子解析器的默认值时使用不同的dest 【参考方案1】:

一种解决方法是在解析后检查input_dir 的值,并在那时替换特定于子解析器的默认值。

import argparse

top_parser = argparse.ArgumentParser()
top_parser.add_argument("--input-dir", type=str)

subparsers = top_parser.add_subparsers()

generate_parser = subparsers.add_parser("generate")
generate_parser.set_defaults(alt_input_dir=".")

process_parser = subparsers.add_parser("process")
process_parser.set_defaults(alt_input_dir="SOME_OTHER_DIR")

args = top_parser.parse_args()
if args.input_dir is None:
    args.input_dir = args.alt_input_dir
del args.alt_input_dir

【讨论】:

谢谢!这种解决方法绝对有效。不过我还是有点困惑。为什么每个子解析器使用set_defaults 函数会导致USE_THIS_DIR 被完全忽略? 这是个好问题;我还没弄清楚这是故意的还是错误的。 这是原开发者的故意行为。请参阅_SubParsersAction.__call__ 方法。 bugs.python.org/issue9351argparse set_defaults on subcommands should override top level set_defaults @hpaulj 这有点不同;子解析器默认值不会覆盖解析器默认值;它覆盖了对选项的显式使用。

以上是关于使用子解析器时,命令行参数被默认值覆盖的主要内容,如果未能解决你的问题,请参考以下文章

argparse详细使用手册

argparse详细使用手册

argparse详细使用手册

launch4j:通过命令行覆盖默认 JVM 堆大小

parser.add_argument()用法——命令行选项参数和子命令解析器

Argparse 命令行解析模块常用参数