#python #argparse
#питон #argparse
Вопрос:
Я использую python argparse для управления параметрами командной строки. Когда количество опций становится большим, справочное сообщение (то, что выводит argparse при передаче --help
) становится пугающим и трудным для чтения просто потому, что оно слишком длинное. Другие программы иногда решают эту проблему, модулируя справочное сообщение: они показывают только «основные параметры» --help
и имеют такие параметры --help-modulea
, как --help-moduleb
, и т.д.
Я думаю, что argparse допускает нечто подобное при наличии подкоманд, по сути, как это делает git: ./script.py command --help
. Однако в моем приложении нет такого понятия, как подкоманды, только большой набор опций (которые, однако, можно красиво сгруппировать).
Есть ли какой-нибудь (разумный) способ сделать это с помощью argparse?
Комментарии:
1. Возможно, вы просто ищете группы аргументов , хотя они не помогают подавить часть выходных данных. Для этого вам нужно будет определить свои собственные обработчики параметров.
2. Я уже использую группы аргументов для группировки аргументов. (очевидно) Однако я не совсем понимаю, что вы подразумеваете под «обработчиками опций»…
3. Посмотрите на код для
print_help
иformat_help
. Вы увидите, какHelpFormatter
вызывается объект и как ему передаются группы. Также посмотрите на_help_action
класс (или какое-то подобное название). Я могу представить себе создание аналогичных подклассов действий и / или форматеров, которые отображают подмножество вашихargument_groups
.
Ответ №1:
Благодаря ответу @hpaulj я должным образом изучил argparse
внутренности и пришел к следующему. Хотя в нем есть некоторые оговорки, я считаю, что это хорошее начало:
class ModularHelpEnabler(argparse.Action):
def __call__(self, parser, namespace, values, option_string = None):
parser.enable_modular_help(self.const)
class ModularArgumentParser(argparse.ArgumentParser):
def __init__(self, *args, **kwargs):
self._modular_action_groups = {}
modular_help_groups = kwargs.pop('modular_help_groups', [])
super().__init__(*args, **kwargs)
self._modular_help_groups = {}
for name in modular_help_groups:
self._modular_help_groups[name] = self.add_argument_group(name)
def add_argument_group(self, *args, **kwargs):
name = kwargs.pop('help_name', None)
help_group = kwargs.pop('help_group', None)
help_text = kwargs.pop('help_group', 'show help for {}')
grp = super().add_argument_group(*args, **kwargs)
if name is not None:
self._modular_action_groups[grp] = name
parser = self
if help_group is not None:
parser = self._modular_help_groups[help_group]
parser.add_argument('--help-{}'.format(name), action=ModularHelpEnabler, nargs=0, const=grp, help = help_text.format(name))
return grp
def enable_modular_help(self, grp):
del self._modular_action_groups[grp]
def format_help(self):
self._action_groups = [
ag for ag in self._action_groups
if ag not in self._modular_action_groups
]
return super().format_help()
Предостережения (которые нетривиально исправить, AFAIK):
--help-foo
не подразумевает--help
.--help-foo
необходимо указать раньше--help
.
К сожалению, --help
напрямую запускает печать справки и завершает работу. Если мы сохраним это поведение, все, что изменяет справочное сообщение, должно быть указано перед --help
самим собой. Мы могли бы отложить печать справки до завершения синтаксического анализа, однако это означало бы, что --help
ошибки синтаксического анализа больше не будут скрываться (как это происходит сейчас), что значительно изменит текущее поведение.