【问题标题】:Python: After raising argparse.ArgumentError, argparse raises generic errorPython:引发 argparse.ArgumentError 后,argparse 引发一般错误
【发布时间】:2013-03-28 20:43:02
【问题描述】:

我为需要遵循精确格式的参数定义了一个自定义正则表达式类型。我使用了另一篇非常有用的帖子 (regex custom type) 中的代码。我的问题是我正在编写单元测试,我预计正则表达式会失败并试图断言 argparse.ArgumentError 已引发( assertRaises(argparse.ArgumentError, parser.parse_args(inargs.split())) )。问题是 argparse 似乎正在捕获 ArgumentError 并引发一般错误,从而阻止我验证失败的原因。我错过了什么吗?

这是回溯:

Error
Traceback (most recent call last):
  File "/Users/markebbert/PyCharmProjects/newproject/unittests.py", line 203, in test_set_operation_parameter
    self.assertRaises(argparse.ArgumentError, parser.parse_args(inargs.split()))
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/argparse.py", line 1688, in parse_args
    args, argv = self.parse_known_args(args, namespace)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/argparse.py", line 1727, in parse_known_args
self.error(str(err))
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/argparse.py", line 2347, in error
    self.exit(2, _('%s: error: %s\n') % (self.prog, message))
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/argparse.py", line 2335, in exit
    _sys.exit(status)
SystemExit: 2

这是我定义的自定义类型和解析器代码:

class RegexValidator(object):
    """
    Performs regular expression match on value.
    If match fails an ArgumentError is raised
    """

    def __init__(self, pattern, statement=None):
        self.pattern = re.compile(pattern)
        self.statement = statement
        if not self.statement:
            self.statement = "must match pattern %s" % self.pattern

    def __call__(self, string):
        match = self.pattern.search(string)
        if not match:
            raise argparse.ArgumentError(None, self.statement)
        return string


operatorRV = RegexValidator(
    "^((\w+)=)?[iIuUcC]\[(\w+(\[\w+(,\w+)*\])?)(:\w+(\[\w+(,\w+)*\])?)*\]$",
    "Set operations must conform to...")

parser = argparse.ArgumentParser(
    description='Compare variants across individuals',
    formatter_class=argparse.ArgumentDefaultsHelpFormatter)

group.add_argument('-s', '--set-operation', dest='operation', nargs='+',
                   type=operatorRV,
                   help="blah.")

这是单元测试:

    # Fail for ending colon
    inargs = "-s out=i[one[id1]:]"
    self.assertRaises(argparse.ArgumentError, parser.parse_args(inargs.split()))

【问题讨论】:

  • Argparse 引发SystemExit,因为这是命令行工具应该做的事情;出错时返回系统退出代码。
  • 您能详细说明一下吗?我不会认为 argparse 是一个命令行工具,因为它是一个 python 模块。与任何模块一样,我希望能够“捕捉” argparse 的错误并自己处理它们。
  • 它是一个build命令行工具的库。我已经添加了答案。

标签: python regex assert argparse


【解决方案1】:

Argparse 是一个命令行解析器,错误总是以调用argparse.exit() 结束,而后者又调用sys.exit() 并带有错误代码。这是设计使然。

对于单元测试,您必须对解析器的.error().exit() 方法进行monkeypatch(可能使用模拟)。 .error() 被调用并带有错误消息并打印使用消息,然后调用 .exit() 并带有退出代码和错误消息。

他们当前的实现:

# ===============
# Exiting methods
# ===============
def exit(self, status=0, message=None):
    if message:
        self._print_message(message, _sys.stderr)
    _sys.exit(status)

def error(self, message):
    """error(message: string)

    Prints a usage message incorporating the message to stderr and
    exits.

    If you override this in a subclass, it should not return -- it
    should either exit or raise an exception.
    """
    self.print_usage(_sys.stderr)
    self.exit(2, _('%s: error: %s\n') % (self.prog, message))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 2017-07-04
    • 1970-01-01
    • 2020-02-26
    • 2017-02-02
    • 1970-01-01
    相关资源
    最近更新 更多