Python3 覆盖 argparse 错误

Posted

技术标签:

【中文标题】Python3 覆盖 argparse 错误【英文标题】:Python3 override argparse error 【发布时间】:2015-10-08 09:07:14 【问题描述】:

我正在创建一个程序作为我学校的作业,除了一件事,我已经完成了它。 我们必须根据执行的方式使用不同的代码使程序退出。在我的程序中,我正在使用“argparse”处理选项,当我使用像“version”这样的内置函数时,我设法覆盖了退出代码,但是如果我编写了一个不存在的选项,那么它就赢了不行。它给了我“无法识别的错误”消息,并以代码“0”退出,我需要它以代码 1 退出。有什么办法吗?一直让我发疯,已经为此苦苦挣扎了好几天...

提前致谢! /感觉

【问题讨论】:

【参考方案1】:

使用 sys.exit(returnCode) 以特定代码退出。显然,在 linux 机器上,您不需要 8 位右移即可获得正确的返回码。

【讨论】:

是的,我知道,问题是如何覆盖 argparse 错误?因为当一个选项无法识别时,它会自动退出并显示错误代码 0,我想覆盖它以便我可以将其更改为退出代码 1... 使用 try except 块捕获错误,并根据异常退出使用不同的代码...提示:使用类似 sys.exc_info() 的方法来检测异常的类型..跨度> 【参考方案2】:

要实现这样的目标,请从 argparse.ArgumentParser 继承并重新实现 exit 方法(或者如果您愿意,也可以是 error 方法)。

例如:

class Parser(argparse.ArgumentParser):
    # the default status on the parent class is 0, we're 
    # changing it to be 1 here ...
    def exit(self, status=1, message=None):
        return super().exit(status, message)

【讨论】:

这是我想我需要做的事情,但我需要实际查看错误是什么,并根据错误给出退出代码,因为正如我所说,退出状态“1”是当错误输入选项时,“0”是程序退出成功和“2”的时候是“命令”是错误的...希望您明白我的意思,抱歉,如果我有点不清楚.. span > 然后覆盖ArgumentParser 上的更多方法,例如error ...主动性等等... 是的,这就是我想做的,但我似乎找不到他们的“名字”或者怎么做?对不起,我对 python 很陌生..【参考方案3】:

来自 Python argparse 文档

https://docs.python.org/3/library/argparse.html#exiting-methods

16.4.5.9. Exiting methods

ArgumentParser.exit(status=0, message=None)

    This method terminates the program, exiting with the specified status and, if given, it prints a message before that.

ArgumentParser.error(message)

    This method prints a usage message including the message to the standard error and terminates the program with a status code of 2.

他们都得到了一个message,并把它传递下去。 error 添加 usage 并将其传递给 exit。您可以在子类解析器中自定义两者。

还有错误捕获和重定向单元测试文件test/test_argparse.py 的示例。

使用try/except 包装器的一个问题是error 信息被写入sys.stderr,而不是合并到sys.exc_info

In [117]: try:
    parser.parse_args(['ug'])
except:
    print('execinfo:',sys.exc_info())
   .....:     
usage: ipython3 [-h] [--test TEST] [--bar TEST] test test
ipython3: error: the following arguments are required: test
execinfo: (<class 'SystemExit'>, SystemExit(2,), <traceback object at 0xb31fb34c>)

退出号在exc_info 中可用,但在消息中没有。

一种选择是重定向sys.stderr,同时重定向try/except 块。

以下是更改exit 方法并将调用包装在try 块中的示例:

In [155]: 
def altexit(status, msg):
    print(status, msg)
    raise ValueError(msg)
   .....: 
In [156]: parser.exit=altexit

In [157]: 
try:                     
    parser.parse_args(['--ug','ug','ug'])
except ValueError:       
    msg = sys.exc_info()[1]
   .....:     
usage: ipython3 [-h] [--test TEST] [--bar TEST] test test
2 ipython3: error: unrecognized arguments: --ug

In [158]: msg
Out[158]: ValueError('ipython3: error: unrecognized arguments: --ug\n')

Python 让我替换现有对象的方法。我不建议在生产代码中这样做,但在尝试想法时很方便。我捕获错误(我对 ValueError 的选择是任意的),并保存消息以供以后显示或测试。

通常错误类型(例如 TypeError、ValueError 等)是公共 API 的一部分,但错误文本不是。它可以在没有太多通知的情况下从一个 Python 版本改进到下一个版本。因此,您需要自行承担测试消息详细信息的风险。

【讨论】:

【参考方案4】:

我通过简单的测试和比较解决了捕获 SystemExit 并确定错误的问题。 感谢大家的帮助!

【讨论】:

以上是关于Python3 覆盖 argparse 错误的主要内容,如果未能解决你的问题,请参考以下文章

python argparse用法

检查 argparse 参数集,或使用默认值,或覆盖

与两个连接的 python3 脚本一起使用时的 argparse 冲突

argparse 错误:无法识别选项

Python模块之argparse

使用 unittest 测试 argparse - 退出错误