除了修补argparse
来源之外,如果在调用parse_args()
时遇到问题,有没有办法控制退出状态代码,例如,缺少必需的开关?
答案 0 :(得分:37)
我不知道任何基于每个参数指定退出代码的机制。您可以捕获SystemExit
上引发的.parse_args()
异常,但我不确定您将如何确定具体导致错误。
编辑:对于前来寻找实用解决方案的人来说,情况如下:
ArgumentError()
被适当地引发。它传递参数实例和消息ArgumentError()
不将参数存储为实例属性,尽管已通过(这很方便)ArgumentError
,重写.error()并从sys.exc_info()获取异常来重新引发ArgumentParser
异常所有这些意味着以下代码 - 虽然丑陋 - 允许我们捕获ArgumentError异常,获取有问题的参数和错误消息,并按我们认为合适:
import argparse
import sys
class ArgumentParser(argparse.ArgumentParser):
def _get_action_from_name(self, name):
"""Given a name, get the Action instance registered with this parser.
If only it were made available in the ArgumentError object. It is
passed as it's first arg...
"""
container = self._actions
if name is None:
return None
for action in container:
if '/'.join(action.option_strings) == name:
return action
elif action.metavar == name:
return action
elif action.dest == name:
return action
def error(self, message):
exc = sys.exc_info()[1]
if exc:
exc.argument = self._get_action_from_name(exc.argument_name)
raise exc
super(ArgumentParser, self).error(message)
## usage:
parser = ArgumentParser()
parser.add_argument('--foo', type=int)
try:
parser.parse_args(['--foo=d'])
except argparse.ArgumentError, exc:
print exc.message, '\n', exc.argument
没有以任何有用的方式进行测试。通常不要责怪我,如果它打破赔偿适用。
答案 1 :(得分:29)
或许捕获SystemExit
异常将是一个简单的解决方法:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('foo')
try:
args = parser.parse_args()
except SystemExit:
print("do something else")
即使是在互动环节中,也适合我。
编辑:看起来@Rob Cowie打败了我。就像他说的那样,这并没有很大的诊断潜力,除非你想要愚蠢并试图从追溯中收集信息。
答案 2 :(得分:26)
所有答案都很好地解释了 argparse 实施的细节。
确实,正如PEP中提出的(并由Rob Cowie指出),应该继承 ArgumentParser 并覆盖错误或退出<的行为/ strong>方法。
在我的情况下,我只是想在错误的情况下用完全帮助打印替换使用打印:
class ArgumentParser(argparse.ArgumentParser):
def error(self, message):
self.print_help(sys.stderr)
self.exit(2, '%s: error: %s\n' % (self.prog, message))
如果覆盖主代码将继续包含minimalistic ..
# Parse arguments.
args = parser.parse_args()
# On error this will print help and cause exit with explanation message.
答案 3 :(得分:9)
从 Python 3.9 开始,这不再那么痛苦。您现在可以通过新的 argparse.ArgumentParser
exit_on_error
实例化参数处理此问题。这是一个示例(从 python 文档稍微修改:argparse#exit_on_error):
parser = argparse.ArgumentParser(exit_on_error=False)
parser.add_argument('--integers', type=int)
try:
parser.parse_args('--integers a'.split())
except argparse.ArgumentError:
print('Catching an argumentError')
exit(-1)
答案 4 :(得分:2)
你必须修补。查看argparse.ArgumentParser.error
,这是内部调用的内容。或者你可以使参数非强制性,然后检查并退出argparse外部。
答案 5 :(得分:1)
您可以使用其中一种退出方法:http://docs.python.org/library/argparse.html#exiting-methods。它应该已经处理了参数无效的情况,但是(假设您已正确定义了参数)。
使用无效参数:
% [ $(./test_argparse.py> /dev/null 2>&1) ] || { echo error }
error # exited with status code 2
答案 6 :(得分:1)
虽然argparse.error是一个方法,而不是一个类,但它不可能&#34;尝试&#34;,&#34;除了&#34;所有&#34;无法识别的论点&#34;错误。如果你想这样做,你需要覆盖argparse中的错误函数:
def print_help(errmsg):
print(errmsg.split(' ')[0])
parser.error = print_help
args = parser.parse_args()
对于无效输入,现在将打印:
unrecognised
答案 7 :(得分:0)
我需要一个简单的方法来在应用程序启动时捕获argparse错误,并将错误传递给wxPython表单。结合以上最佳答案可以得出以下解决方案:
import argparse
# sub class ArgumentParser to catch an error message and prevent application closing
class MyArgumentParser(argparse.ArgumentParser):
def __init__(self, *args, **kwargs):
super(MyArgumentParser, self).__init__(*args, **kwargs)
self.error_message = ''
def error(self, message):
self.error_message = message
def parse_args(self, *args, **kwargs):
# catch SystemExit exception to prevent closing the application
result = None
try:
result = super().parse_args(*args, **kwargs)
except SystemExit:
pass
return result
# testing -------
my_parser = MyArgumentParser()
my_parser.add_argument('arg1')
my_parser.parse_args()
# check for an error
if my_parser.error_message:
print(my_parser.error_message)
运行它:
>python test.py
the following arguments are required: arg1