【问题标题】:How can I tell argparse not to exit if there are not enough args?如果没有足够的参数,我如何告诉 argparse 不要退出?
【发布时间】:2020-03-25 01:41:24
【问题描述】:

我正在尝试扩展 argparse 以使用配置文件以及 CLI 参数。我想传入配置文件中的所有选项如果有未知选项则不退出。

我的想法是先致电parse_known_args 了解新选项,然后致电 parse_known_args 再次与 sys.argv。这使我可以准确地警告配置文件中的未知选项,而不是 CLI 上的选项。但是,如果没有足够的参数,argparse 会在第一次调用 parse_known_args 后退出。有没有办法告诉它不要退出?

我的代码如下所示:

class Parser(argparse.ArgumentParser):
    def parse_known_args(self, args=None, namespace=None):
        config = {}
        for file in get_config_files(self.prog):
            for key, value in try_parse(file, self.default_ext).items():
                config[key] = value, file

        new_args = []
        for key, (val, _) in config.items():
            new_args.append('--' + key)
            new_args.append(val)

        # override configuration with argparse's builtin parsing
        # makes CLI options take precedence over config files
        # ----- This is where argparse exits -----
        parsed_config, unknown = super().parse_known_args(new_args, namespace)
        #print("finished first call to known_args")

        for key in unknown[::2]:
            key = key[2:]
            _, filename = config[key]
            warnings.warn("unknown option '%s' (from %s)" % (key, filename))
        #print(parsed_config)

        return super().parse_known_args(args, parsed_config)

示例用法如下所示:

>>> from pyautoconfig import Parser
>>> p = Parser(prog='test')
>>> p.add_argument('positional')
_StoreAction(option_strings=[], dest='positional', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> p.parse_args(['positional arg'])
usage: test [-h] positional
test: error: the following arguments are required: positional

请注意,即使我传递了位置参数,它也是如何以错误退出的。我怎样才能避免这种情况?

我找到了How to call parse_args() twice on the same set of arguments in Python's argparse?,但它处理的参数太多,而不是太少(推荐的解决方案是使用parse_known_args)。

如果有帮助,完整代码是 on GitHub

【问题讨论】:

  • 我查看了源代码,我什至无法捕捉到 ArgumentError 因为parse_known_args 吞下它并首先退出:github.com/python/cpython/blob/3.8/Lib/argparse.py#L1799 :(
  • 您可能在这里陷入了“XY 问题”。我会重新考虑您要做什么:mywiki.wooledge.org/XyProblem 换句话说:尝试使用不同的工具来解析配置文件,而不是用于命令行参数的东西。
  • @KevinAnderson 问题是我想保留 argparse 的所有功能,例如 typemutually_exclusive_argschoices。我不想让 argparse 解析 JSON 或类似的东西,我自己做所有这些。
  • 您可以在解析器遇到错误时更改行为。 parser.errorparser.exit 可以定制。请注意,required_actions 案例使用 self.error(....)
  • @hpaulj 这不起作用,因为它不检查互斥参数。请注意,在检查所需参数之后进行检查:github.com/python/cpython/blob/3.8/Lib/argparse.py#L2038。此外,我不想捕捉每一个错误,只捕捉这个特定的错误。

标签: python argparse


【解决方案1】:

我发现了一个黑客!如果需要的操作不存在,Argparse 只会引发错误:https://github.com/python/cpython/blob/3.8/Lib/argparse.py#L2033。因此,如果不需要任何操作,则不会引发错误。

新代码:

        # HACK: make all these not required to avoid argparse exiting
        # HACK: if there are too few args
        temp_actions = []
        for action in self._actions:
            if action.required:
                action.required = False
                temp_actions.append(action)
        parsed_config, unknown = super().parse_known_args(new_args, namespace)

        # HACK: reset the actions to their previous state
        for action in temp_actions:
            action.required = True

【讨论】:

    猜你喜欢
    • 2022-09-28
    • 2021-07-30
    • 1970-01-01
    • 2021-07-07
    • 2021-09-11
    • 2013-05-26
    • 2022-12-17
    • 2018-09-23
    • 2020-06-04
    相关资源
    最近更新 更多