Возможно, я нашел решение здесь. Правда, это грязный хак, но он работает.
Примечание: все следующее относится к Python 3.3.2.
Согласно ответу здесь , parse_args
проверяет, какие действия требуются, и выдает ошибку, если какое-либо из них отсутствует. Я предлагаю переопределить это поведение.
Подклассом ArgumentParser
мы можем определить новый метод ArgumentParser.error
(оригинальный здесь ), который будет проверять, была ли выброшена ошибка из-за отсутствия некоторых аргументов, и предпринимать необходимые действия. Код следует:
import argparse
import sys
from gettext import gettext as _
class ArgumentParser(argparse.ArgumentParser):
skip_list = []
def error(self, message):
# Let's see if we are missing arguments
if message.startswith('the following arguments are required:'):
missingArgs = message.split('required: ')[1].split(', ')
newArgs = [] # Creating a list of whatever we should not skip but is missing
for arg in missingArgs:
if arg not in self.skip_list:
newArgs.append(arg)
else:
self.skip_list.remove(arg) # No need for it anymore
if len(newArgs) == 0:
return # WARNING! UNTESTED! MAY LEAD TO SPACETIME MELTDOWN!
else: # Some required stuff is still missing, so we show a corrected error message
message = _('the following arguments are required: %s') % ', '.join(newArgs)
self.print_usage(sys.stderr) # Original method behavior
args = {'prog': self.prog, 'message': message}
self.exit(2, _('%(prog)s: error: %(message)s\n') % args)
Новый метод сначала проверяет, является ли ошибка причиной отсутствия аргументов в командной строке (см. здесь для кода, который генерирует ошибку). Если это так, метод получает имена аргументов из сообщения об ошибке и помещает их в список (missingArgs
).
Затем мы перебираем этот список и проверяем, какие аргументы должны быть пропущены, а какие еще необходимы. Чтобы определить, какие аргументы нужно пропустить, мы сравниваем их с skip_list
. Это поле в нашем подклассе ArgumentParser
, которое должно содержать имена аргументов, которые нужно пропустить, даже когда они требуются синтаксическому анализатору. Обратите внимание, что аргументы, которые попадают в skip_list
, удаляются из него при их обнаружении.
Если в командной строке все еще отсутствуют обязательные аргументы, метод выдает исправленное сообщение об ошибке. Однако, если все пропущенные аргументы должны быть пропущены, метод возвращает.
ПРЕДУПРЕЖДЕНИЕ! Исходное определение ArgumentParser.error
гласит, что если оно переопределено в подклассе , оно не должно возвращать , а скорее выходить или вызывать исключение. Следовательно, то, что показано здесь, потенциально небезопасно и может привести к сбою вашей программы, к вашему компьютеру или к тому же к худшему - ЭТО МОЖЕТ УПОТРЕБИТЬ ВСЕЙ ЧАЙ . Тем не менее, кажется , как в данном конкретном случае (без обязательных аргументов), можно безопасно вернуться из метода. Но это не может быть. Вы были предупреждены.
Чтобы заполнить skip_list
, мы могли бы использовать такой код:
class SpecialHelp(argparse._HelpAction):
def __call__(self, parser, namespace, values, option_string=None):
parser.print_help()
print()
for action in parser._actions:
if action != self and action.required:
parser.skip_list.append(argparse._get_action_name(action))
Этот конкретный класс имитирует встроенное действие help
, но вместо выхода он вставляет все оставшиеся необходимые аргументы в skip_list
.
Надеюсь, мой ответ поможет и удачи.