处理 Python ArgumentParser 中的错误
handle errors in Python ArgumentParser
我想手动处理 parse_args()
在参数值未知时抛出错误的情况。例如:
如果我有以下名为 script.py
的 python 文件:
argp = argparse.ArgumentParser(description='example')
argp.add_argument('--compiler', choices=['default', 'clang3.4', 'clang3.5'])
args = argp.parse_args()
并且我 运行 具有以下参数的脚本 python script.py --compiler=foo
它抛出以下错误:
error: argument --compiler: invalid choice: 'foo' (choose from 'default', 'clang3.4', 'clang3.5')
SystemExit: 2
我需要做什么才能自己处理此行为而不是脚本自行退出?一个想法是子类化 argparse.ArgumentParser
并覆盖 parse_args()
或者只是猴子修补该方法,但我想知道是否有更好的方法不需要覆盖标准库行为?
定义选择的全部意义在于让解析器抱怨不在列表中的值。但还有一些替代方案:
省略选项(如果需要,将它们包含在帮助文本中),并在解析后进行自己的测试。 argparse
不必为您做所有事情。它的主要目的是弄清楚你的用户想要什么。
重新定义 parser.error
方法(最好通过子类化)以重定向来自 sys.exit
的错误。但是您必须解析错误消息以区分此错误和解析器可能引发的其他错误。
定义一个 type
函数来检查选择,并进行默认替换。
“--compiler”选项的解析是这样的:
- 获取
--compiler
标志后的字符串参数
- 通过
type
函数传递。默认值为 lambda x:x
。 int
将其转换为整数等。加 ValueError
是值错误。
- 根据
choices
列表(如果有)检查返回值
- 使用
action
将值添加到命名空间(默认只是存储它)。
任何这些步骤中的错误都会产生一个 ArgumentError
,它被 parser.error
方法捕获并传递给 parser.exit
方法。
由于 store_action
发生在 type
和 choices
检查之后,自定义操作不会绕过它们的错误。
这是一个可能的 type
解决方案(未测试)
def compile_choices(astr):
if astr in ['default', 'clang3.4', 'clang3.5']:
return astr
else:
return 'default'
# could raise ValueError('bad value') if there are some strings you don't like
argp.add_argument('--compiler', type=compile_choices)
=================
如果 compile_choices
采用其他参数,例如选择列表或默认值,您需要在解析之前包含一些定义这些值的原因。
接受二进制字符串表示的示例:
parser.add_argument('--binary', type=lambda x: int(x, base=2),
help='integer in binary format', default='1010')
或
parser.add_argument('--binary', type=functools.partial(int, base=2), default='1010')
我想手动处理 parse_args()
在参数值未知时抛出错误的情况。例如:
如果我有以下名为 script.py
的 python 文件:
argp = argparse.ArgumentParser(description='example')
argp.add_argument('--compiler', choices=['default', 'clang3.4', 'clang3.5'])
args = argp.parse_args()
并且我 运行 具有以下参数的脚本 python script.py --compiler=foo
它抛出以下错误:
error: argument --compiler: invalid choice: 'foo' (choose from 'default', 'clang3.4', 'clang3.5')
SystemExit: 2
我需要做什么才能自己处理此行为而不是脚本自行退出?一个想法是子类化 argparse.ArgumentParser
并覆盖 parse_args()
或者只是猴子修补该方法,但我想知道是否有更好的方法不需要覆盖标准库行为?
定义选择的全部意义在于让解析器抱怨不在列表中的值。但还有一些替代方案:
省略选项(如果需要,将它们包含在帮助文本中),并在解析后进行自己的测试。
argparse
不必为您做所有事情。它的主要目的是弄清楚你的用户想要什么。重新定义
parser.error
方法(最好通过子类化)以重定向来自sys.exit
的错误。但是您必须解析错误消息以区分此错误和解析器可能引发的其他错误。定义一个
type
函数来检查选择,并进行默认替换。
“--compiler”选项的解析是这样的:
- 获取
--compiler
标志后的字符串参数 - 通过
type
函数传递。默认值为lambda x:x
。int
将其转换为整数等。加ValueError
是值错误。 - 根据
choices
列表(如果有)检查返回值 - 使用
action
将值添加到命名空间(默认只是存储它)。
任何这些步骤中的错误都会产生一个 ArgumentError
,它被 parser.error
方法捕获并传递给 parser.exit
方法。
由于 store_action
发生在 type
和 choices
检查之后,自定义操作不会绕过它们的错误。
这是一个可能的 type
解决方案(未测试)
def compile_choices(astr):
if astr in ['default', 'clang3.4', 'clang3.5']:
return astr
else:
return 'default'
# could raise ValueError('bad value') if there are some strings you don't like
argp.add_argument('--compiler', type=compile_choices)
=================
如果 compile_choices
采用其他参数,例如选择列表或默认值,您需要在解析之前包含一些定义这些值的原因。
接受二进制字符串表示的示例:
parser.add_argument('--binary', type=lambda x: int(x, base=2),
help='integer in binary format', default='1010')
或
parser.add_argument('--binary', type=functools.partial(int, base=2), default='1010')