python argparse – необязательный аргумент append с выбором

У меня есть сценарий, где я спрашиваю у пользователя список предварительно определенных действий для выполнения. Я также хочу, чтобы возможность принимать определенный список действий, когда пользователь ничего не определяет. однако, похоже, что попытка сделать это вместе невозможна.

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

acts = ['clear','copy','dump','lock'] p = argparse.ArgumentParser() p.add_argument('action', nargs='*', action='append', choices=acts, default=[['dump', 'clear']]) args = p.parse_args([]) >>> usage: [-h] [{clear,copy,dump,lock} [{clear,copy,dump,lock} ...]] : error: argument action: invalid choice: [['dump', 'clear']] (choose from 'clear', 'copy', 'dump', 'lock') 

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

 acts = ['clear','copy','dump','lock'] p = argparse.ArgumentParser() p.add_argument('action', nargs='*', action='append', choices=acts, default=[['dump', 'clear']]) args = p.parse_args(['lock']) args >>> Namespace(action=[['dump', 'clear'], ['dump']]) 

  • многопроцессорность в консоли IPython на компьютере Windows - если требование __name_
  • ctypes: построить указатель из произвольного целого
  • Как узнать общее количество кадров в файле cv2 в python
  • Переопределение метода добавления после наследования из списка Python
  • eval импортировать модуль
  • Doc, rtf и txt в python
  • operator.itemgetter или лямбда
  • Python argparse как функция
  • 5 Solutions collect form web for “python argparse – необязательный аргумент append с выбором”

    То, что вам нужно, может быть выполнено с помощью настраиваемого argparse.Action как в следующем примере:

     import argparse parser = argparse.ArgumentParser() class DefaultListAction(argparse.Action): CHOICES = ['clear','copy','dump','lock'] def __call__(self, parser, namespace, values, option_string=None): if values: for value in values: if value not in self.CHOICES: message = ("invalid choice: {0!r} (choose from {1})" .format(value, ', '.join([repr(action) for action in self.CHOICES]))) raise argparse.ArgumentError(self, message) setattr(namespace, self.dest, values) parser.add_argument('actions', nargs='*', action=DefaultListAction, default = ['dump', 'clear'], metavar='ACTION') print parser.parse_args([]) print parser.parse_args(['lock']) 

    Результат скрипта:

     $ python test.py Namespace(actions=['dump', 'clear']) Namespace(actions=['lock']) 

    В документации (http://docs.python.org/dev/library/argparse.html#default) говорится:

    Для позиционных аргументов с nargs равными? или *, значение по умолчанию используется, если аргумент командной строки отсутствует.

    Тогда, если мы это сделаем:

     acts = ['clear','copy','dump','lock'] p = argparse.ArgumentParser() p.add_argument('action', nargs='*', choices=acts, default='clear') print p.parse_args([]) 

    Мы получаем то, что ожидаем

     Namespace(action='clear') 

    Проблема заключается в том, что вы поместили список по умолчанию. Но я видел это в документе,

     parser.add_argument('bar', nargs='*', default=[1, 2, 3], help='BAR!') 

    Итак, я не знаю 🙁

    Во всяком случае, это обходное решение, которое делает нужную работу:

     import sys, argparse acts = ['clear','copy','dump','lock'] p = argparse.ArgumentParser() p.add_argument('action', nargs='*', choices=acts) args = ['dump', 'clear'] # I set the default here ... if sys.argv[1:]: args = p.parse_args() print args 

    Вы можете проверить, выполняет ли пользователь действие (в этом случае анализирует его как обязательный, аргумент позиции) или не выполняет никаких действий (в этом случае проанализируйте его как необязательный аргумент со значением по умолчанию):

     import argparse import sys acts = ['clear', 'copy', 'dump', 'lock'] p = argparse.ArgumentParser() if sys.argv[1:]: p.add_argument('action', nargs = '*', choices = acts) else: p.add_argument('--action', default = ['dump', 'clear']) args = p.parse_args() print(args) 

    при запуске дает следующие результаты:

     % test.py Namespace(action=['dump', 'clear']) % test.py lock Namespace(action=['lock']) % test.py lock dump Namespace(action=['lock', 'dump']) 

    У вас, вероятно, есть и другие варианты для синтаксического анализа. В этом случае вы можете использовать parse_known_args для анализа других параметров, а затем обрабатывать unknown аргументы во втором проходе:

     import argparse acts = ['clear', 'copy', 'dump', 'lock'] p = argparse.ArgumentParser() p.add_argument('--foo') args, unknown = p.parse_known_args() if unknown: p.add_argument('action', nargs = '*', choices = acts) else: p.add_argument('--action', default = ['dump', 'clear']) p.parse_args(unknown, namespace = args) print(args) 

    при запуске дает следующие результаты:

     % test.py Namespace(action=['dump', 'clear'], foo=None) % test.py --foo bar Namespace(action=['dump', 'clear'], foo='bar') % test.py lock dump Namespace(action=['lock', 'dump'], foo=None) % test.py lock dump --foo bar Namespace(action=['lock', 'dump'], foo='bar') 

    Действие было добавлено из-за параметра action = 'append' ', который вы передали в argparse.

    После удаления этого параметра аргументы, переданные пользователем, будут отображаться сами по себе, но программа выкидывает ошибку, когда аргументы не передаются.

    Добавление префикса '-' к первому параметру разрешает это самым ленивым способом.

     acts = ['clear','copy','dump','lock'] p = argparse.ArgumentParser() p.add_argument('--action', nargs='*', choices=acts, default=[['dump', 'clear']]) args = p.parse_args() 

    Недостатком этого подхода является то, что перед параметрами, передаваемыми пользователем, должно предшествовать «-action», например:

     app.py --action clear dump copy 

    Я закончил делать следующее:

    • нет append
    • добавьте пустой список к возможным вариантам, иначе пустые входные прерывания
    • без по умолчанию
    • затем проверьте пустой список и установите фактическое значение по умолчанию в этом случае

    Пример:

     parser = argparse.ArgumentParser() parser.add_argument( 'is', type=int, choices=[[], 1, 2, 3], nargs='*', ) args = parser.parse_args(['1', '3']) assert args.a == [1, 3] args = parser.parse_args([]) assert args.a == [] if args.a == []: args.a = [1, 2] args = parser.parse_args(['1', '4']) # Error: '4' is not valid. 
    Interesting Posts

    Тестирование модулей Python: автоматический запуск отладчика при неудачном тестировании

    Как переопределить поле родительского класса

    Переименуйте ключ словаря

    Как вы включаете код фляжки / jinja2 внутри файла уценки?

    Python Selenium с Phantomjs – Не удалось щелкнуть: ReferenceError: не найти переменную

    Как преобразовать строку из CP-1251 в UTF-8?

    Как определить конфигурационные переменные / константы в Google App Engine (Python)?

    Веб-скребок: ограничение на запросы в минуту / час на одном домене?

    TensorFlow – получить текущее значение переменной

    Как напечатать целое число со знаком как шестнадцатеричное число в дополнении к python?

    traitlets.traitlets.TraitError в Пичарме

    Техника удаления общих слов (и их множественных версий) из строки

    Загрузка файлов из s3 рекурсивно с помощью boto python.

    Добавить, изменить, удалить celery.schedules во время выполнения

    Структура Django REST – фильтрация по параметру запроса

    Python - лучший язык программирования в мире.