Argparse: Обязательные аргументы, перечисленные в разделе "необязательные аргументы"?
Я использую следующий простой код для анализа некоторых аргументов; обратите внимание, что один из них необходим. К сожалению, когда пользователь запускает script без предоставления аргумента, отображаемый текст использования/помощи не указывает на наличие необязательного аргумента, который я считаю очень запутанным. Как я могу заставить python указать, что аргумент не является необязательным?
Вот код:
import argparse
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='Foo')
parser.add_argument('-i','--input', help='Input file name', required=True)
parser.add_argument('-o','--output', help='Output file name', default="stdout")
args = parser.parse_args()
print ("Input file: %s" % args.input )
print ("Output file: %s" % args.output )
При запуске над кодом без предоставления требуемого аргумента я получаю следующий вывод:
usage: foo.py [-h] -i INPUT [-o OUTPUT]
Foo
optional arguments:
-h, --help show this help message and exit
-i INPUT, --input INPUT
Input file name
-o OUTPUT, --output OUTPUT
Output file name
Ответы
Ответ 1
Параметры, начинающиеся с -
или --
, обычно считаются необязательными. Все остальные параметры являются позиционными параметрами и как таковые требуются по дизайну (например, аргументы позиционной функции). Можно потребовать дополнительные аргументы, но это немного противоречит их дизайну. Поскольку они по-прежнему являются частью непозиционных аргументов, они все равно будут перечислены под путаным заголовком "необязательные аргументы", даже если они необходимы. Однако отсутствующие квадратные скобки в части использования показывают, что они действительно необходимы.
См. также документацию :
В общем случае модуль argparse предполагает, что флаги, такие как -f и -bar, указывают необязательные аргументы, которые всегда можно опустить в командной строке.
Примечание.. Обязательные параметры обычно считаются плохими, потому что пользователи ожидают, что параметры будут необязательными, и поэтому их следует избегать, когда это возможно.
При этом заголовки "позиционные аргументы" и "необязательные аргументы" в справке генерируются двумя группами аргументов, в которых аргументы автоматически разделяются. Теперь вы можете "взломать" его и изменить имя необязательных, но гораздо более элегантным решением было бы создать еще одну группу для "требуемых именованных аргументов" (или как бы вы их называть):
parser = argparse.ArgumentParser(description='Foo')
parser.add_argument('-o', '--output', help='Output file name', default='stdout')
requiredNamed = parser.add_argument_group('required named arguments')
requiredNamed.add_argument('-i', '--input', help='Input file name', required=True)
parser.parse_args(['-h'])
usage: [-h] [-o OUTPUT] -i INPUT
Foo
optional arguments:
-h, --help show this help message and exit
-o OUTPUT, --output OUTPUT
Output file name
required named arguments:
-i INPUT, --input INPUT
Input file name
Ответ 2
Поскольку я предпочитаю перечислять обязательные аргументы перед необязательными, я обхожу их с помощью:
parser = argparse.ArgumentParser()
parser._action_groups.pop()
required = parser.add_argument_group('required arguments')
optional = parser.add_argument_group('optional arguments')
required.add_argument('--required_arg', required=True)
optional.add_argument('--optional_arg')
return parser.parse_args()
и это выводит:
usage: main.py [-h] [--required_arg REQUIRED_ARG]
[--optional_arg OPTIONAL_ARG]
required arguments:
--required_arg REQUIRED_ARG
optional arguments:
--optional_arg OPTIONAL_ARG
Я могу жить без "помощи", появляющейся в группе необязательных аргументов.
Ответ 3
Здание @Karl Rosaen
parser = argparse.ArgumentParser()
optional = parser._action_groups.pop() # Edited this line
required = parser.add_argument_group('required arguments')
# remove this line: optional = parser...
required.add_argument('--required_arg', required=True)
optional.add_argument('--optional_arg')
parser._action_groups.append(optional) # added this line
return parser.parse_args()
и это выводит:
usage: main.py [-h] [--required_arg REQUIRED_ARG]
[--optional_arg OPTIONAL_ARG]
required arguments:
--required_arg REQUIRED_ARG
optional arguments:
-h, --help show this help message and exit
--optional_arg OPTIONAL_ARG
Ответ 4
Еще раз, построение @RalphyZ
Этот не нарушает открытый API.
from argparse import ArgumentParser, SUPPRESS
# Disable default help
parser = ArgumentParser(add_help=False)
required = parser.add_argument_group('required arguments')
optional = parser.add_argument_group('optional arguments')
# Add back help
optional.add_argument(
'-h',
'--help',
action='help',
default=SUPPRESS,
help='show this help message and exit'
)
required.add_argument('--required_arg', required=True)
optional.add_argument('--optional_arg')
Который покажет то же, что и выше, и должен выжить в будущих версиях:
usage: main.py [-h] [--required_arg REQUIRED_ARG]
[--optional_arg OPTIONAL_ARG]
required arguments:
--required_arg REQUIRED_ARG
optional arguments:
-h, --help show this help message and exit
--optional_arg OPTIONAL_ARG