Обработка нескольких значений для одного параметра с помощью 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.
Ответы
Ответ 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']