2015-12-09 1 views
1

Эта программа:Argparse предлагает бессмысленный порядок помощи использования текста линии

import argparse 

parser = argparse.ArgumentParser() 
parser.add_argument('files', metavar='INPUT', nargs='*', 
    help='File(s) containing words to include. If none given, stdin will be used.') 
parser.add_argument('-x', '--exclude', nargs='*', 
    help='File(s) containing words to exclude.') 
args = parser.parse_args() 
print args.files 
print args.exclude 

производит этот выход при запуске в Python 2.7.9:

$ python prog.py --help 
usage: prog.py [-h] [-x [EXCLUDE [EXCLUDE ...]]] [INPUT [INPUT ...]] 

positional arguments: 
    INPUT     File(s) containing words to include. If 
         none given, stdin will be used. 

optional arguments: 
    -h, --help   show this help message and exit 
    -x [EXCLUDE [EXCLUDE ...]], --exclude [EXCLUDE [EXCLUDE ...]] 
         File(s) containing words to exclude. 

Однако, что «помощь» выход инструктирует пользователя использовать бессмысленное упорядочение аргументов. Это бессмысленно, потому что если используется опция -x, то не будут обнаружены аргументы INPUT.

Argparse должно вместо того, чтобы сообщить пользователю использовать этот порядок:

usage: prog.py [-h] [INPUT [INPUT ...]] [-x [EXCLUDE [EXCLUDE ...]]] 

два вопроса:

  1. Является ли это ошибка в argparse? (Я думаю, что это так.)
  2. Независимо от того, является ли это ошибкой, как я могу исправить это так, чтобы $ python prog.py --help выдал текст справки, который я хочу (см. Выше), желательно как DRY как можно?

ответ

1

При формировании usage линии, помечается аргументы помещается первым, позиционных после того. Это соответствует общему использованию командной строки. Он не прилагает никаких усилий для оценки того, является ли это лучшим выбором или нет.

Простейший способ для этого - предоставить пользовательский параметр usage.

(там есть быть SO вопросами изменений порядка аргументов в строке использования. Решение требует настроек в HelpFormatter класса. Change argparse usage message argument order )

Как вы заметили, когда * позиционный помещаются после * необязательно, все аргументы присваиваются необязательному. Вы можете использовать '--' для разделения двух списков аргументов.

Существует ошибка/проблема с патчем, которая должна улучшить обработку, когда positional принимает известное количество аргументов (например, по умолчанию). Он делает это, отмечая, что позиция требует аргумента, поэтому она резервирует ее для нее. Но в * * случае positional удовлетворен нет, поэтому он не имеет возможности узнать, как разделить аргументы между 2.

мне нравится идея превращения, что postional в помеченных аргумент. Это должно уменьшить неоднозначность, присущую множеству аргументов *.

+0

Цель argparse - уменьшить нагрузку на программиста, когда (генерируя текст справки для) анализирует аргументы командной строки. Если argparse собирается генерировать строку использования «автоматически», то по умолчанию она должна поступать правильно. Во что бы то ни стало пусть сначала ставит помеченные аргументы во всех случаях, когда это имеет смысл, но это абсолютно не следует делать в тех случаях, когда это было бы бессмысленно, потому что это не помогает программисту почти так много. Программисту не нужно бороться с его инструментами. Вот почему я думаю, что это ошибка. Спасибо за ответ на оба моих вопроса, хотя :) – sampablokuper

+2

Приглашаем вас отправить исправление, исправляющее это. Метод, который генерирует линию использования, довольно длинный и хрупкий. Он может использовать некоторое улучшение. – hpaulj

1

Самый простой способ - добавить usage="..." в argparse.ArgumentParser().

Просматривая источник argparse, я нашел способ прибегнуть аргументы, которые могли бы быть немного грязный:

class MyHelpFormatter(argparse.HelpFormatter): 

    def _format_actions_usage(self, actions, groups): 
     actions.sort(key=lambda a: bool(a.option_strings and a.nargs != 0)) 
     return super(MyHelpFormatter, self)._format_actions_usage(actions, groups) 

parser = argparse.ArgumentParser(formatter_class = MyHelpFormatter) 
+0

Спасибо. Это дает мне ответ на q.2. Это не идеально, поскольку это не СУХОЙ: мне придется обновлять его каждый раз, когда я добавляю/удаляю аргументы. Любые мысли по q.1? – sampablokuper

+0

@sampablokuper: Обновлен с возможностью прибегать. Я думаю, это можно назвать ошибкой. – eph

+0

eph, это достаточно грязно, что я не совсем понимаю (пока?), Как это работает :) Тем не менее, очень хорошая работа, чтобы добиться переупорядочения текста использования; и спасибо за подтверждение! – sampablokuper

1

Добавить '-f', '--files' к опции ввода:

import argparse 

parser = argparse.ArgumentParser() 
parser.add_argument('-f', '--files', metavar='INPUT', nargs='*', required=True, 
    help='File(s) containing words to include. If none given, stdin will be used.') 
parser.add_argument('-x', '--exclude', nargs='*', 
    help='File(s) containing words to exclude.') 
args = parser.parse_args() 
print args.files 

шоу:

usage: argparse_test.py [-h] [-f [INPUT [INPUT ...]]] 
        [-x [EXCLUDE [EXCLUDE ...]]] 

optional arguments: 
    -h, --help   show this help message and exit 
    -f [INPUT [INPUT ...]], --files [INPUT [INPUT ...]] 
         File(s) containing words to include. If none given, 
         stdin will be used. 
    -x [EXCLUDE [EXCLUDE ...]], --exclude [EXCLUDE [EXCLUDE ...]] 
        File(s) containing words to exclude. 
print args.exclude 

Вы можете сделать «файлы» обязательными. В документах:

В общем случае модуль argparse предполагает, что флаги, такие как -f и -bar, указывают необязательные аргументы, которые всегда можно опустить в командной строке. Для того, чтобы сделать необходимую опцию, True может быть определен для требуемого = ключевого слова аргумента add_argument():

+0

Просто сделайте это обязательным с помощью 'required = True'. –

+0

Спасибо. 'INPUT' является обязательным, поэтому я не делал этого в первую очередь. OTOH, правда, что предоставление одного или нескольких файлов * необязательно, поэтому, возможно, я должен был это сделать. Хм, я подумаю об этом снова :) – sampablokuper

Смежные вопросы