Python 3.9.1 argparse exit_on_error 在某些情况下不起作用

问题描述 投票:0回答:2

我正在编写一个包含元命令的 REPL。元命令可以接受选项和参数,我正在尝试使用 argparse 来处理它们。因此,如果用户没有正确使用该命令,我不想完全退出程序。我最多想打印一条使用消息并继续 REPL。这是我正在尝试的基本想法:

import argparse

p = argparse.ArgumentParser(exit_on_error=False)

p.add_argument('foo')

try:
    p.parse_args([])   # I want to catch the case of a user not supplying a required positional arg
except argparse.ArgumentError:
    print("error detected")

但是,运行上面的代码片段给了我这个(并在之后立即退出):

usage: test.py [-h] foo
test.py: error: the following arguments are required: foo

Python 3.9 文档是这样说的:

通常,当您将无效的参数列表传递给

parse_args()
ArgumentParser
方法时,它将退出并显示错误信息。

如果用户想手动捕获错误,可以通过将

exit_on_error
设置为
False
来启用该功能:

我可能误解了“无效参数列表”的含义(以及文档中给出的示例某些作品),但我认为空参数列表适用于这种情况。

我意识到还有其他方法可以处理这个问题(并且我已经成功测试了其中的一两个),但我只是想确保我没有遗漏

exit_on_error
参数的某些内容。也就是说,有人知道为什么这不起作用吗?

python argparse
2个回答
7
投票

该参数仅处理一类错误,该错误是在处理特定参数时引发的。对必需参数的测试的处理方式不同,并且不会因此参数而转移。我怀疑这是在 Python 错误/问题上提出的,但我并没有对此给予太多关注。更改

parser.error
parser.exit
方法适用于这两类错误。


3
投票

这是已知问题。根据讨论不太可能很快修复。

...这里真正的问题是用户使用了太多的库.....我们要么保留旧的“错误”行为,要么破坏用户现有的代码。

对我来说,这导致我的测试失败。我通过修补

ArgumentParser.exit()
方法解决了这个问题。

    @pytest.mark.parametrize("args", [
        '',
        '--junk-kw',
        '--junk-kw-with-val 123',
        'junk-positional',
    ])
    def test_invalid_args(self, args):
        """tests all validations done by argparse"""
        with pytest.raises(argparse.ArgumentError), mock.patch(
                'my.module.argparse.ArgumentParser.exit',
                side_effect=argparse.ArgumentError(None, '')
        ):
            my_module.MyClass().parse_args(*args.split())
© www.soinside.com 2019 - 2024. All rights reserved.