#python #parameters #argparse
#python #параметры #argparse
Вопрос:
Есть ли какой-либо способ вручную упорядочить параметры с помощью модуля argparse?
На данный момент у меня есть это:
usage: cons_test.py [-h] [-l L] [-R] [-O O] [-o O] [-T T] <STR_file> <PDB_file>
но я хотел бы иметь позиционные (и поэтому необязательные) параметры перед необязательными параметрами, например:
usage: cons_test.py <STR_file> <PDB_file> [-h] [-l L] [-R] [-O O] [-o O] [-T T]
Что я должен изменить в своем коде для достижения этого порядка?
Комментарии:
1. Самый простой шаг, особенно для одноразового использования, — это написать свою собственную
usage
строку.
Ответ №1:
Вариант решения Martijn Pieters — удалите все перенос строк и отобразите аргументы в том порядке, в котором они определены.
class RawUsageHelpFormatter(argparse.HelpFormatter):
def _format_usage(self, usage, actions, groups, prefix):
# use actions in the order that they are define
# no line wrapping
if prefix is None:
prefix = 'usage: '
if usage is not None:
usage = usage % dict(prog=self._prog)
elif usage is None and not actions:
usage = '%(prog)s' % dict(prog=self._prog)
elif usage is None:
prog = '%(prog)s' % dict(prog=self._prog)
format = self._format_actions_usage
action_usage = format(actions, groups)
usage = ' '.join([s for s in [prog, action_usage] if s])
return '%s%snn' % (prefix, usage)
пример вывода:
usage: stack24221824.py [-h] <STR_file> [-t T] <PDB_file> [-l {txt,html,pdf}] [-R] [-O {txt,html,pdf}]
[-h]
является первым, потому что анализатор создает это сразу. Затем я определил STR
, -t
, PDB
, и т.д. При необходимости, я думаю, вы могли бы подавить справку add_help=True
и позже определить свой собственный -h
аргумент. Если вы хотите перенос строки, вам нужно беспокоиться о том, где разрешено разбивать строку, и об отступах для последующих строк.
Ответ №2:
Не без предоставления собственного класса форматирования. Создание того, который отменяет необязательные и позиционные аргументы, может быть выполнено с помощью подкласса, но обратите внимание, что это зависит от внутренних методов, которые могут меняться между версиями Python.
Следующий класс будет работать в Python 2 и 3, поскольку переопределенный метод по-прежнему вызывается таким же образом, но только для подгонки текста по ширине терминала (с использованием COLUMNS
переменной среды, по умолчанию 80 столбцов минус 2 символа заполнения):
class SwappedOrderHelpFormatter(argparse.HelpFormatter):
def _format_actions_usage(self, actions, groups):
# split optionals from positionals
optionals = []
positionals = []
for action in actions:
if action.option_strings:
optionals.append(action)
else:
positionals.append(action)
return super(SwappedOrderHelpFormatter, self)._format_actions_usage(
positionals optionals, groups)
Скажите argparse
, чтобы использовать это при создании вашего анализатора аргументов:
parser = argparse.ArgumentParser(
# ....
formatter_class=SwappedOrderHelpFormatter,
# ....
)
Если ваш текст не будет соответствовать ширине большинства терминалов, вам необходимо полностью переопределить argparse.HelpFormatter._format_usage()
метод и поменять порядок переменных optionals
and positionals
.
ДЕМОНСТРАЦИЯ:
>>> parser = argparse.ArgumentParser(prog='PROG', formatter_class=SwappedOrderHelpFormatter)
>>> parser.add_argument('-l', action='store_true')
_StoreTrueAction(option_strings=['-l'], dest='l', nargs=0, const=True, default=False, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('-R')
_StoreAction(option_strings=['-R'], dest='R', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('STR_file')
_StoreAction(option_strings=[], dest='STR_file', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('PDB_file')
_StoreAction(option_strings=[], dest='PDB_file', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.print_help()
usage: PROG STR_file PDB_file [-h] [-l] [-R R]
positional arguments:
STR_file
PDB_file
optional arguments:
-h, --help show this help message and exit
-l
-R R
Комментарии:
1. Я полагаю, вам придется внести дополнительные изменения для обработки длинного многострочного использования.
2. @hpaulj: а, я понимаю, что ты имеешь в виду.
if len(prefix) len(usage) > text_width:
затем позиционные значения форматируются отдельно от дополнительных.3. Этот
_format_usage
метод является хрупким. Он возвращает строку из_format_actions_usage
, и пытается разделить ее наactions
group
единицы и, а затем объединить их обратно в строки. Мой патч в bugs.python.org/issue11874 является переписыванием этих методов.4. @hpaulj: На самом деле весь
HelpFormatter
класс довольно хрупкий.5. В отдельном скрипте ваш код работает, но как только я добавляю новый аргумент, а именно
parser.add_argument("-O", "--output_file_name", choices=["txt", "html"], default="txt|html", help="output file name")
порядок возвращается к нормальному:usage: SwappedOrder.py [-h] [-l {bic,pf1}] [-R] [-O {txt,html}] STR_file PDB_file
что заставляет некоторые аргументы работать, а некоторые нет? Я пропускаю параметр аргумента am?