除了修改源代码之外,如果调用时出现问题,例如缺少必需的开关argparse
,是否有任何方法可以控制退出状态代码?parse_args()
8 回答
我不知道有任何机制可以在每个参数的基础上指定退出代码。您可以捕获SystemExit
引发的异常,.parse_args()
但我不确定您将如何确定具体导致错误的原因。
编辑:对于任何来此寻找实用解决方案的人,情况如下:
ArgumentError()
当 arg 解析失败时适当地引发。它被传递参数实例和消息ArgumentError()
不将参数存储为实例属性,尽管被传递(这很方便)ArgumentError
可以通过子类化ArgumentParser
、覆盖 .error() 并从 sys.exc_info() 获取异常来重新引发异常
这意味着下面的代码——虽然丑陋——允许我们捕获 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
未以任何有用的方式进行测试。通常的不责备我,如果它破坏赔偿适用。
所有答案都很好地解释了argparse实现的细节。
实际上,正如PEP中提出的(并由 Rob Cowie 指出),应该继承ArgumentParser并覆盖错误或退出方法的行为。
就我而言,我只想用完整的帮助打印替换使用打印以防出现错误:
class ArgumentParser(argparse.ArgumentParser):
def error(self, message):
self.print_help(sys.stderr)
self.exit(2, '%s: error: %s\n' % (self.prog, message))
在覆盖主代码的情况下将继续包含简约..
# Parse arguments.
args = parser.parse_args()
# On error this will print help and cause exit with explanation message.
也许捕捉SystemExit
异常将是一个简单的解决方法:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('foo')
try:
args = parser.parse_args()
except SystemExit:
print("do something else")
对我有用,即使在交互式会话中也是如此。
编辑:看起来@Rob Cowie 打败了我。就像他说的那样,这没有太大的诊断潜力,除非你想变得愚蠢并尝试从追溯中收集信息。
从 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)
您可以使用其中一种现有方法:http ://docs.python.org/library/argparse.html#exiting-methods 。但是,它应该已经处理了参数无效的情况(假设您已经正确定义了参数)。
使用无效参数:
% [ $(./test_argparse.py> /dev/null 2>&1) ] || { echo error }
error # exited with status code 2
你得修修补补。看看argparse.ArgumentParser.error
,这是在内部调用的。或者您可以使参数成为非强制性的,然后在 argparse 之外检查并退出。
虽然 argparse.error 是一种方法而不是一个类,但它不可能“尝试”、“排除”所有“无法识别的参数”错误。如果你想这样做,你需要覆盖 argparse 中的错误函数:
def print_help(errmsg):
print(errmsg.split(' ')[0])
parser.error = print_help
args = parser.parse_args()
在无效输入上,它现在将打印:
unrecognised
我需要一个简单的方法来在应用程序启动时捕获 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