Подтвердить что ты не робот

Обработка нескольких значений для одного параметра с помощью getopt/optparse?

Можно ли получить несколько значений для одного параметра с помощью getopt или optparse, как показано в следующем примере:

./hello_world -c arg1 arg2 arg3 -b arg4 arg5 arg6 arg7

Обратите внимание, что количество фактических значений для каждого параметра (-c, -b) может быть 1 или 100. Я не хочу использовать: ./hello_world -c "arg1 arg2 arg3" -b "arg4 arg5 arg6 arg7"

Мне кажется, что это может быть невозможно (и, возможно, в нарушение POSIX), пожалуйста, исправьте меня, если я ошибаюсь.

Я видел примеры, где все необязательные параметры в конце строки (./hello_world -c arg1 -b arg1 arg2 arg3) могут быть собраны... но не для первой из нескольких опций.

Я хочу, чтобы мое приложение работало на широком диапазоне платформ с разными версиями Python, поэтому я не смотрел на argparser.

4b9b3361

Ответ 1

Да, это можно сделать с помощью optparse.

Это пример:

./test.py --categories=aaa --categories=bbb --categories ccc arg1 arg2 arg3

который печатает:

arguments: ['arg1', 'arg2', 'arg3']
options: {'categories': ['aaa', 'bbb', 'ccc']}

Полный рабочий пример ниже:

#!/usr/bin/env python

import os, sys
from optparse import OptionParser
from optparse import Option, OptionValueError

VERSION = '0.9.4'

class MultipleOption(Option):
    ACTIONS = Option.ACTIONS + ("extend",)
    STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
    TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
    ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",)

    def take_action(self, action, dest, opt, value, values, parser):
        if action == "extend":
            values.ensure_value(dest, []).append(value)
        else:
            Option.take_action(self, action, dest, opt, value, values, parser)


def main():
    PROG = os.path.basename(os.path.splitext(__file__)[0])
    long_commands = ('categories')
    short_commands = {'cat':'categories'}
    description = """Just a test"""
    parser = OptionParser(option_class=MultipleOption,
                          usage='usage: %prog [OPTIONS] COMMAND [BLOG_FILE]',
                          version='%s %s' % (PROG, VERSION),
                          description=description)
    parser.add_option('-c', '--categories', 
                      action="extend", type="string",
                      dest='categories', 
                      metavar='CATEGORIES', 
                      help='comma separated list of post categories')

    if len(sys.argv) == 1:
        parser.parse_args(['--help'])

    OPTIONS, args = parser.parse_args()
    print "arguments:", args
    print "options:", OPTIONS

if __name__ == '__main__':
    main()

Дополнительная информация на http://docs.python.org/library/optparse.html#adding-new-actions

Ответ 2

Несмотря на претензии других комментариев, это возможно с помощью vanilla optparse, по крайней мере, с python 2.7. Вам просто нужно использовать action = "append". Из docs:

parser.add_option("-t", "--tracks", action="append", type="int")

Если -t3 отображается в командной строке, optparse выполняет эквивалент:

options.tracks = []
options.tracks.append(int("3"))

Если немного позже, --tracks = 4 видно, он делает:

options.tracks.append(int("4"))

Ответ 3

Жаль, что опаздывала на вечеринку, но я просто решил это с помощью optparse, используя флаг nargs.

parser.add_option('-c','--categories', dest='Categories', nargs=4 )

http://docs.python.org/2/library/optparse.html#optparse.Option.nargs

Также стоит отметить, что argparse (предложенный unutbu) теперь является частью стандартного дистрибутива python, в то время как optparse устарел.

Ответ 4

Вы можете сделать это с помощью параметра nargs в argparse, который поставляется с Python2.7 и загружаемым здесь.

Я думаю, что это одно из улучшений, добавленных в argparse, который не находится в optparse. Итак, к сожалению, я не думаю, что есть хороший способ справиться с этим с помощью optparse или getopt (который еще старше).

Быстрое и грязное решение может состоять в том, чтобы отказаться от optparse/getop/argparse и просто разобрать sys.argv самостоятельно.

Или, идя в противоположном направлении, вы можете рассмотреть возможность упаковки замороженной копии argparse (~ 88K) (переименованной в argparse_static) с вашей программой и импортируя его следующим образом:

try:
    import argparse
except ImportError:
    import argparse_static as argparse

Таким образом, программа будет использовать argparse, если она установлена, и будет использовать argparse_static, если это не так. Лучше всего, вам не придется переписывать много кода, поскольку argparse становится стандартным.

Ответ 5

Ни getopt, ни optparse не поддерживают это из коробки. Кроме того, в режиме по умолчанию (GNU) дополнительные аргументы будут обрабатываться как вкрапленные args, то есть становятся доступными в качестве аргументов с левым аргументом в конце обработки.

Соглашение должно требовать повторного упоминания одного и того же аргумента, т.е.

./hello_world -c arg1 -c arg2 -c arg3 -b arg4 -b arg5 -b arg6 -b arg7

Это будет поддерживаться.

Если вы абсолютно хотите, чтобы он работал так, как вы указываете (т.е. оба -b и -c расширяются до следующего аргумента или конец списка аргументов), вы можете взломать что-то вместе на основе optparse. Наследовать от OptionParser и переопределить _process_short_opts. Если это один из ваших вариантов, обработайте его в подклассе, иначе перейдите в базовый класс.

Ответ 6

Другой вариант - определить разделитель и обработать его локально, например параметры в команде mount.

Например, если , можно использовать как разделитель:

...
args, _ = getopt.getopt(sys.argv[1:],'b:')
for flag, arg in args:
  if flag=='-b': all_arguments = arg.split(',')
...

$ ./test -b opt1,opt2,opt3

То же самое для космоса! Но тогда ваши пользователи должны правильно его процитировать.

$ ./test -b 'opt1 opt2 opt3'

Ответ 7

Более простой:

make_option(
    "-c",
    "--city",
    dest="cities",
    action="append",
    default=[],
    help="specify cities",
)

Добавить действие - это самое простое решение этой проблемы.

Ответ 8

Я не знаю питона. я попытался сделать это, не используя optparse

import sys
class Args(object):
    def __init__(self,option,args):
        self.option=option
        self.args=args
    def getOption(self):
        return self.option
    def getArgs(self):
        return self.args
    def show(self):
        print "option "+self.option+" Args : "+str(self.args)

list = sys.argv
list.pop(0)
of = 0
lst=[]
argList=[]
opt =''
for item in list:
    if item.startswith("-"):
        if of == 1:
            argList.append(Args(opt,lst))
            of = 0
            lst =[]
        opt = item
    else:
        of =1
        lst.append(item)
if of == 1:
    argList.append(Args(opt, lst))

for item in argList:
    item.show()

Пример

python test.py -as as cc xx -sn likh gd -ik jhjh
option -as Args : ['as', 'cc', 'xx']
option -sn Args : ['likh', 'gd']
option -ik Args : ['jhjh']