Помимо использования метода argparse
, существует ли способ управления кодом состояния выхода, если возникает проблема, когда вызывается parse_args()
, например, отсутствующий требуемый коммутатор?
Python argparse и управление/переопределение кода состояния выхода
Ответ 1
Я не знаю какого-либо механизма для указания кода выхода для каждого аргумента. Вы можете поймать исключение SystemExit
, поднятое на .parse_args()
, но я не уверен, как вы могли бы выяснить, что конкретно вызвало ошибку.
EDIT: Для тех, кто приступает к поиску практического решения, следующая ситуация:
-
ArgumentError()
возникает должным образом, когда анализ аргументов не выполняется. Он передал экземпляр аргумента и сообщение -
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 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
Не проверен каким-либо полезным способом. Применяется обычное возмещение ответственности за отказ от ответственности.
Ответ 2
Возможно, перехват исключения SystemExit
будет простым обходным путем:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('foo')
try:
args = parser.parse_args()
except SystemExit:
print("do something else")
Работает для меня даже в интерактивном сеансе.
Изменить: Похоже, @Rob Cowie избил меня до переключателя. Как он сказал, у этого нет очень большого диагностического потенциала, если вы не хотите глупо и попытаться собрать информацию из трассы.
Ответ 3
Все ответы прекрасно объясняют детали реализации argparse.
Действительно, как было предложено в PEP (и указано Rob Cowie), следует наследовать ArgumentParser и переопределить поведение error или выйти.
В моем случае я просто хотел заменить печать использования полной копией справки в случае ошибки:
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.
Ответ 4
Вы можете использовать один из методов: http://docs.python.org/library/argparse.html#exiting-methods. Однако он должен обрабатывать ситуации, когда аргументы недействительны (при условии, что вы правильно определили свои аргументы).
Использование недопустимых аргументов:
% [ $(./test_argparse.py> /dev/null 2>&1) ] || { echo error }
error # exited with status code 2
Ответ 5
Тебе пришлось бы возиться. Посмотрите argparse.ArgumentParser.error
, что и называется внутренним. Или вы можете сделать аргументы не обязательными, а затем проверить и выйти за пределы argparse.
Ответ 6
Хотя argparse.error - это метод, а не класс, его невозможно "попробовать", "за исключением" всех ошибок "непризнанных аргументов". Если вы хотите сделать это, вам нужно переопределить функцию ошибки из argparse:
def print_help(errmsg):
print(errmsg.split(' ')[0])
parser.error = print_help
args = parser.parse_args()
на недействительном вводе, он теперь будет печатать:
unrecognised