我希望Python argparse抛出异常而不是显示用法。

49

我认为这是不可能的,但我希望能够自己处理argparse产生的异常。

例如:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--foo', help='foo help', required=True)
try:
    args = parser.parse_args()
except:
    do_something()
当我运行它时:
$ myapp.py
usage: myapp --foo foo
myapp: error: argument --foo is required

但我想它应该属于例外情况。


2
你没有按照 argparse 的设计来使用它,那么你想要做什么? - Chris Morgan
10
改变原本优秀的库的工作方式以适应特定项目并进行调整,这并不是一件坏事。 - joedborg
5
实际上,您已经可以这样做了。只需要捕获SystemExit并将sys.stderr替换为其他对象即可。 - Bakuriu
1
根据您想要做什么,修改参数本身可能更好。--foo的参数是可选的吗?您能定义一个自定义操作来处理它吗?这些操作可能比覆盖argparse退出决策更清晰。 - chepner
Python 3.9在ArgumentParser()中添加了一个exit_on_error参数,但它尚未对缺少必需选项或无法识别的选项抛出错误(?)。请参见https://bugs.python.org/issue41255。 - user650654
显示剩余3条评论
2个回答

82
你可以子类化 ArgumentParser 并重写 error 方法,在错误发生时执行不同的操作:
class ArgumentParserError(Exception): pass

class ThrowingArgumentParser(argparse.ArgumentParser):
    def error(self, message):
        raise ArgumentParserError(message)

parser = ThrowingArgumentParser()
parser.add_argument(...)
...

1
想到可能是这样的。感谢清晰的回答。 - joedborg
3
我希望能够避免这种情况,但我很高兴它是一个选项。你知道,当我收到“error: too few arguments”通知时,我想打印出帮助菜单;我的argparse设置需要至少一个参数才能成功运行,但我认为在用户不必使用“-h”参数运行脚本的情况下打印出这些命令是有礼貌的。就像这样:`parser.set_error('too few arguments', method_to_deal_with_error)`如果我想要这个功能,我想我可以随时提交一个错误报告。谢谢! - NuclearPeon

27

在我的情况下,argparse会打印出“参数过少”然后退出。在查看argparse代码后,我发现它只是在打印一些信息后调用了sys.exit()。由于sys.exit()除了抛出SystemExit异常外什么也不做,因此您可以捕获此异常。

因此,尝试使用以下代码,看看是否适用于您的情况。

    try:
        args = parser.parse_args(args)
    except SystemExit:
        .... your handler here ...
        return

1
是的,这个选项在Bakuriu的评论中已经提到了。test_argparse.py单元测试文件使用了这种方法,同时重新定义error来创建一个ErrorRaisingArgumentParser类。 - hpaulj
3
错误信息会被抛出到 stderr,有没有办法捕获它? - Raj
1
@Raj,你可以将 stderr 暂时重定向到另一个流/文件对象,例如:https://dev59.com/TGw15IYBdhLWcg3wJ4cR#6796752 - umi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接