首页 > 解决方案 > 想自定义python argparse模块生成的错误

问题描述

import argparse    
parser = argparse.ArgumentParser()

group = parser.add_mutually_exclusive_group()
group.add_argument("-f", "--filepath", help="Input the file path")
group.add_argument("-d", "--dirpath", help="Input the directory path")

例如,如果我同时使用选项 -f 和 -d,我会收到以下由 python 生成的错误:error: argument -d/--dirpath: expected one argument

但我想自定义错误,它应该由我定义。

标签: python-2.7argparse

解决方案


2140:~/mypy$ python3 stack50552334.py
Namespace(dirpath=None, filepath=None)

这些都是在 Actionnargs和可用字符串不匹配时产生的。虽然消息格式相同,但它是根据参数名称定制的:

2140:~/mypy$ python3 stack50552334.py -f
usage: stack50552334.py [-h] [-f FILEPATH | -d DIRPATH]
stack50552334.py: error: argument -f/--filepath: expected one argument
2140:~/mypy$ python3 stack50552334.py -d
usage: stack50552334.py [-h] [-f FILEPATH | -d DIRPATH]
stack50552334.py: error: argument -d/--dirpath: expected one argument
2140:~/mypy$ python3 stack50552334.py -f -d
usage: stack50552334.py [-h] [-f FILEPATH | -d DIRPATH]
stack50552334.py: error: argument -f/--filepath: expected one argument
2141:~/mypy$ python3 stack50552334.py -f foo -d
usage: stack50552334.py [-h] [-f FILEPATH | -d DIRPATH]
stack50552334.py: error: argument -d/--dirpath: expected one argument

但是当两个标志都提供了预期的参数时,mutually_exclusive_group测试就会发挥作用,并引发它自己的错误。

2141:~/mypy$ python3 stack50552334.py -f foo -d dir
usage: stack50552334.py [-h] [-f FILEPATH | -d DIRPATH]
stack50552334.py: error: argument -d/--dirpath: not allowed with argument -f/--filepath

第一类消息产生于:

def _match_argument(self, action, arg_strings_pattern):
    # match the pattern for this action to the arg strings
    nargs_pattern = self._get_nargs_pattern(action)
    match = _re.match(nargs_pattern, arg_strings_pattern)

    # raise an exception if we weren't able to find a match
    if match is None:
        nargs_errors = {
            None: _('expected one argument'),
            OPTIONAL: _('expected at most one argument'),
            ONE_OR_MORE: _('expected at least one argument'),
        }
        default = ngettext('expected %s argument',
                           'expected %s arguments',
                           action.nargs) % action.nargs
        msg = nargs_errors.get(action.nargs, default)
        raise ArgumentError(action, msg)

    # return the number of arguments matched
    return len(match.group(1))

是的_别名gettext.gettext。因此,可以使用这种机制自定义消息。 https://docs.python.org/3/library/gettext.html

from gettext import gettext as _, ngettext

我对这种多语言本地化没有任何经验。

mutually_exclusive错误出现在:

    def take_action(action, argument_strings, option_string=None):
        ...
        # error if this argument is not allowed with other previously
        # seen arguments, assuming that actions that use the default
        # value don't really count as "present"
        if argument_values is not action.default:
            seen_non_default_actions.add(action)
            for conflict_action in action_conflicts.get(action, []):
                if conflict_action in seen_non_default_actions:
                    msg = _('not allowed with argument %s')
                    action_name = _get_action_name(conflict_action)
                    raise ArgumentError(action, msg % action_name)

同样,有gettext定制的可能性。

自定义 argparse.py

当然,没有什么可以阻止您修改argparse.py文件副本并将其放置在您自己的目录中,以便加载它而不是默认目录。

解析后测试

如果错误的措辞mutually_exclusive让您感到困扰(与expected one argument错误相反,您可以从解析器中省略该组,并在解析后进行自己的测试。如果用户为两者提供了非默认值args.filepathargs.dirpathcall parser.error('your own message'),或者提出您自己的错误。


推荐阅读