2016-11-21 2 views
3

Я использую argparse, и у меня есть различные группы, у которых есть свои собственные варианты.Настроить помощь среди групп в argparse

Теперь с --help вариант Я не хочу показывать все параметры по умолчанию. Для -help нужно показать только набор параметров групп.

Другие варианты группы должны подбираться на основе других вариантов помощи, так как --help_1, --help_2:

Например:

--help' to show Group 2 and 3 
--help_1' to show Group 11 and 12 
--help_2' to show Group 22 and 23 

Я знаю, что мы можем отключить опцию --help по умолчанию с помощью add_help = False, но как я могу отображать только выбранные группы, которые могут помочь?

Мы можем получить список групп из синтаксического анализа с использованием _action_groups атрибутов, но они не подвергают какой-либо print_help() вариант как таковой.

Мой пример кода:

parser = argparse.ArgumentParser(add_help=False) 

parser.add_argument('--help_a', action='store_true') 
parser.add_argument('--help_b', action='store_true') 

group1 = parser.add_argument_group("Feature 1") 
group1.add_argument('--foo1') 
group2 = parser.add_argument_group("Feature 2") 
group2.add_argument('--foo2') 
group3 = parser.add_argument_group("Feature 3") 
group3.add_argument('--foo3') 

# TODO: --help_a to only print "Feature 1" groups help 
# and --help_b to print Feature 2 and 3's help. 

EDIT: Использование subparser и добавление парсеры (вместо группы) будет решать выше. Но subparser не подходит для моего случая, поскольку я все время разбираю его, мне нужно только настроить помощь для отображения.

+0

Почему бы не пройти его через 'less'? 'python command.py --help | less' –

+0

Это не кажется правильным в моем случае. Я не хочу, чтобы внешний пользователь использовал мой API или скрипт для анализа на их стороне. Сценарий должен обрабатывать его самостоятельно. – baky

+0

Не понимаю. Можете ли вы добавить дополнительную информацию о том, какие группы вы используете, и почему вы хотите показывать разные страницы справки? –

ответ

1

Вот обычай format_help подход:

import argparse 

def format_help(self, groups=None): 
    # self == parser 
    formatter = self._get_formatter() 

    # usage 
    formatter.add_usage(self.usage, self._actions, 
         self._mutually_exclusive_groups) 

    # description 
    formatter.add_text(self.description) 

    if groups is None: 
     groups = self._action_groups 

    # positionals, optionals and user-defined groups 
    for action_group in groups: 
     formatter.start_section(action_group.title) 
     formatter.add_text(action_group.description) 
     formatter.add_arguments(action_group._group_actions) 
     formatter.end_section() 

    # epilog 
    formatter.add_text(self.epilog) 

    # determine help from format above 
    return formatter.format_help() 

<your parser> 

args = parser.parse_args() 
# _action_groups[:2] are the default ones 
if args.help_a: 
    print(format_help(parser, [parser._action_groups[2]])) 
    parser.exit() 
if args.help_b: 
    print(format_help(parser, parser._action_groups[3:])) 
    parser.exit() 

Sample работает

1444:~/mypy$ python stack40718566.py --help_a 
usage: stack40718566.py [-h] [--help_a] [--help_b] [--foo1 FOO1] [--foo2 FOO2] 
         [--foo3 FOO3] 

Feature 1: 
    --foo1 FOO1 

1444:~/mypy$ python stack40718566.py --help_b 
usage: stack40718566.py [-h] [--help_a] [--help_b] [--foo1 FOO1] [--foo2 FOO2] 
         [--foo3 FOO3] 

Feature 2: 
    --foo2 FOO2 

Feature 3: 
    --foo3 FOO3 

Так что это так же, как по умолчанию format_help, за исключением groups параметр. Он может даже заменить метод по умолчанию в подклассе ArgumentParser.

Мы также можем создать пользовательский класс Help Action, который ведет себя как стандартная справка, за исключением того, что для него требуется какой-то параметр group_list. Но это пост-синтаксическое действие проще кодировать и тестировать.

+0

Спасибо, я тоже думал об аналогичных строках, как в переопределении самого класса _ActionGroup, который принимает в качестве дополнительного параметра «help_bucket», что означает, какую помощь использовать. Но этот будет делать трюк, и он чище и прост. Одна вещь, однако, использование отображает все параметры по умолчанию, это можно легко решить, добавив только необходимые действия в add_usage. еще раз спасибо – baky

0

Я рекомендую против того, что вы пытаетесь сделать.

You are solving a problem that isn't yours to solve. Это работа вашего сценария, чтобы вернуть информацию об использовании. Это не ваша проблема, если это много текста. То, что вы можете сделать, вы делаете: Поместите аргументы в группы, которые имеют смысл для пользователя. Но сумма текста не является проблемой структуры данных, но и для представления данных.

Во-вторых, вы будете следовать за конвенцией никто не использует. Обычно существуют

man command 
command --help 
command subcommand --help 

Все, что было бы смущает пользователей в первый раз.

Кроме того, если у вас много групп аргументов, человеку всегда нужно проконсультироваться с --help, чтобы узнать, какие --help_* им придется проконсультироваться следующим образом. Это может разочаровать пользователям, когда вы можете сразу же его представить в --help.

Если вы используете несколько страниц справки, вы должны предотвратить повторное использование вашего текста справки. Поиск, например: Невозможно выполнить поиск нескольких страниц без переключения между ними вручную.

Правильный способ сделать - передать текст через paginator как less.Это позволяет пользователям читать текст постранично, поиск через него (нажмите /) или сохранить его в файл:

command --help | less 

Для удобства некоторые команды, как git log, даже проверить, если output is an interactive terminal и automatically pass the output through less. Это означало бы

command --help > help.txt 

сохраняет помощь в файл, в то время как

command --help 

показывает текст справки в пагинации и поиск.

Так что моя рекомендация для вас как на Windows, и UNIX является

import os 
import sys 
import argparse 
import subprocess 


def less(data): 
    if sys.stdout.isatty(): 
     if os.name == 'posix': 
      cmd = "less" 
     elif os.name == 'nt': 
      cmd = "more" 

     process = subprocess.Popen([cmd], stdin=subprocess.PIPE) 

     try: 
      process.stdin.write(data) 
      process.communicate() 
     except IOError: 
      pass 
    else: 
     print data 


class MyArgumentParser(argparse.ArgumentParser): 
    def print_help(self, file=None): 
     less(self.format_help()) 
     self.exit() 


parser = MyArgumentParser(prog='PROG') 
group1 = parser.add_argument_group("Feature 1") 
group1.add_argument('--foo1') 
group2 = parser.add_argument_group("Feature 2") 
group2.add_argument('--foo2') 
group3 = parser.add_argument_group("Feature 3") 
group3.add_argument('--foo3') 
# parse some argument lists 
print parser.parse_args() 
+0

Спасибо за подробный ответ. Что касается вашего вышеупомянутого комментария, в котором упоминается, как люди не смогут посмотреть, какую помощь использовать, я добавлю параметр «help_all», так что это не проблема. BTW, я все равно посмотрю, возможно ли что-то похожее на мой вопрос – baky

+0

@hpaulj опубликовал решение для этого же. Пожалуйста, посмотрите – baky