Python: Как сделать опцию обязательной в optparse? - PullRequest
35 голосов
/ 10 декабря 2010

Я прочитал это http://docs.python.org/release/2.6.2/library/optparse.html

Но мне не очень понятно, как сделать опцию обязательной в optparse?

Я пытался установить "required =1 ", но я получил ошибку:

недопустимые аргументы ключевого слова: требуется

Я хочу, чтобы мой сценарий требовал ввода --file пользователем.Я знаю, что ключевое слово action выдает ошибку, если вы не указали значение для --file, для которого action="store_true".

Ответы [ 9 ]

63 голосов
/ 10 декабря 2010

Вы можете легко реализовать необходимую опцию.

parser = OptionParser(usage='usage: %prog [options] arguments')
parser.add_option('-f', '--file', 
                        dest='filename',
                        help='foo help')
(options, args) = parser.parse_args()
if not options.filename:   # if filename is not given
    parser.error('Filename not given')
10 голосов
/ 15 декабря 2011

В справочном сообщении каждой требуемой переменной я записываю строку «[REQUIRED]» в начале, чтобы пометить ее для последующего анализа, затем я могу просто использовать эту функцию, чтобы обернуть ее вокруг:

def checkRequiredArguments(opts, parser):
    missing_options = []
    for option in parser.option_list:
        if re.match(r'^\[REQUIRED\]', option.help) and eval('opts.' + option.dest) == None:
            missing_options.extend(option._long_opts)
    if len(missing_options) > 0:
        parser.error('Missing REQUIRED parameters: ' + str(missing_options))

parser = OptionParser()
parser.add_option("-s", "--start-date", help="[REQUIRED] Start date")
parser.add_option("-e", "--end-date", dest="endDate", help="[REQUIRED] End date")
(opts, args) = parser.parse_args(['-s', 'some-date'])
checkRequiredArguments(opts, parser)
6 голосов
/ 02 марта 2016

Поскольку if not x не работает для некоторых (отрицательных, нулевых) параметров,

и для предотвращения множества тестов if, я предпочитаю что-то вроде этого:

required="host username password".split()

parser = OptionParser()
parser.add_option("-H", '--host', dest='host')
parser.add_option("-U", '--user', dest='username')
parser.add_option("-P", '--pass', dest='password')
parser.add_option("-s", '--ssl',  dest='ssl',help="optional usage of ssl")

(options, args) = parser.parse_args()

for r in required:
    if options.__dict__[r] is None:
        parser.error("parameter %s required"%r)
3 голосов
/ 04 декабря 2015

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

parser = OptionParser(usage='usage: %prog [options] arguments')
parser.add_option('-f', '--file', dest='filename')
(options, args) = parser.parse_args()
if 'filename' not in options.__dict__:
  parser.error('Filename not given')
3 голосов
/ 31 июля 2012

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

Мои критерии для обязательного параметра - значение параметра должно быть не None, и этот параметр не имеет значения по умолчанию (пользователь не указал add_option (default = "...", ...).

def parse_cli():
    """parse and check command line options, shows help message
    @return: dict - options key/value
    """
    import __main__
    parser = OptionParser(description=__main__.__doc__)
    parser.add_option("-d", "--days", dest="days",
                      help="Number of days to process")
    parser.add_option("-p", "--period", dest="period_length",default="2",
              help="number or hours per iteration, default value=%default hours")    
    (options, args) = parser.parse_args()

    """get dictionary of options' default values. 
       in this example: { 'period_length': '2','days': None}"""
    defaults = vars(parser.get_default_values())
    optionsdict = vars(options)

    all_none = False        
    for k,v in optionsdict.items():
        if v is None and defaults.get(k) is None:
            all_none = True


    if all_none:
        parser.print_help()
        sys.exit()
    return optionsdict
1 голос
/ 28 апреля 2017

Существует как минимум два способа реализации требуемых опций с optparse. Как упомянуто на странице документов , optparse не мешает вам реализовать необходимые опции, но и не дает вам большой помощи в этом. Ниже приведены примеры, найденные в файлах, распространяемых вместе с источником.

Хотя обратите внимание, что optparse модуль устарел с версии 2.7 и не будет развиваться дальше. Вы должны использовать argparse module .


Версия 1: добавьте метод в OptionParser, который приложения должны вызывать после анализа аргументов:

import optparse

class OptionParser (optparse.OptionParser):

    def check_required (self, opt):
      option = self.get_option(opt)

      # Assumes the option's 'default' is set to None!
      if getattr(self.values, option.dest) is None:
          self.error("%s option not supplied" % option)


parser = OptionParser()
parser.add_option("-v", action="count", dest="verbose")
parser.add_option("-f", "--file", default=None)
(options, args) = parser.parse_args()

print "verbose:", options.verbose
print "file:", options.file
parser.check_required("-f")

Источник: docs/lib/required_1.txt


Версия 2: Расширить Option и добавить обязательный атрибут; расширьте OptionParser, чтобы обеспечить наличие необходимых параметров после синтаксического анализа:

import optparse

class Option (optparse.Option):
    ATTRS = optparse.Option.ATTRS + ['required']

    def _check_required (self):
        if self.required and not self.takes_value():
            raise OptionError(
                "required flag set for option that doesn't take a value",
                 self)

    # Make sure _check_required() is called from the constructor!
    CHECK_METHODS = optparse.Option.CHECK_METHODS + [_check_required]

    def process (self, opt, value, values, parser):
        optparse.Option.process(self, opt, value, values, parser)
        parser.option_seen[self] = 1


class OptionParser (optparse.OptionParser):

    def _init_parsing_state (self):
        optparse.OptionParser._init_parsing_state(self)
        self.option_seen = {}

    def check_values (self, values, args):
        for option in self.option_list:
            if (isinstance(option, Option) and
                option.required and
                not self.option_seen.has_key(option)):
                self.error("%s not supplied" % option)
        return (values, args)


parser = OptionParser(option_list=[
    Option("-v", action="count", dest="verbose"),
    Option("-f", "--file", required=1)])
(options, args) = parser.parse_args()

print "verbose:", options.verbose
print "file:", options.file

Источник: docs/lib/required_2.txt

0 голосов
/ 26 июня 2017

Я бы использовал библиотеку argparse со встроенными функциями:

PARSER.add_argument("-n", "--namespace", dest="namespace", required=True,
              help="The path within the repo to the data base")

ссылка на argparse

0 голосов
/ 23 ноября 2015

Поскольку модуль optparse устарел с версии 2.7, вы, вероятно, найдете здесь несколько более свежих примеров: Требуется мертвый простой пример argparse: 1 аргумент, 3 результата

0 голосов
/ 30 октября 2014

Я также застрял на Python 2.6 (тоскует по python2.7 и argparse, которые не только имеют обязательные аргументы, но и позволяют мне указать, что должен быть указан один из набора);Мой подход требует второго прохода, но позволяет запрашивать пропущенные аргументы, если только он не работает в пакетном режиме:

# from myscript
import helpers
import globalconfig 
parser = optparse.OptionParser(usage=myheader,epilog=myfooter)
parser.add_option("-L","--last",
                  action="store",dest="last_name",default="",
                  help="User's last (family) name; prompted for if not supplied"
                 )
parser.add_option("-y","--yes",
                  action="store_true",dest="batch_flag",default=False,
                  help="don't prompt to confirm actions (batch mode)"
                  )
[...]
(options, args) = parser.parse_args()
globalconfig.batchmode = options.batch_flag
[...]
last = prompt_if_empty(options.last_name,
        "Last name (can supply with \"-L\" or \"--last\" option):")


# from helpers.py
def prompt_if_empty(variable,promptstring):
    if not variable:
        if globalconfig.batchmode:
            raise Exception('Required variable missing.')
        print "%s" %promptstring
        variable = raw_input(globalconfig.prompt)
    return variable

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

В другом ответе на этот вопрос упоминается parser.error, с которым я не был знаком, когда писал код, но, возможно, был лучшим выбором.

...