С помощью модуля optparse в Python, как создать опцию, которая принимает переменное число аргументов? - PullRequest
12 голосов
/ 22 июня 2009

С Perl Getopt::Long вы можете легко определить параметры командной строки, которые принимают переменное число аргументов:

foo.pl --files a.txt             --verbose
foo.pl --files a.txt b.txt c.txt --verbose

Есть ли способ сделать это напрямую с помощью модуля optparse Python? Насколько я могу судить, атрибут опции nargs может использоваться для указания фиксированного количества аргументов опции, и я не видел других альтернатив в документации.

Ответы [ 6 ]

21 голосов
/ 05 февраля 2010

Это заняло у меня некоторое время, чтобы понять, но вы можете использовать действие обратного вызова для ваших опций, чтобы сделать это. Посмотрите, как в этом примере я выбираю произвольное количество аргументов для флага "--file".

from optparse import OptionParser,

def cb(option, opt_str, value, parser):
        args=[]
        for arg in parser.rargs:
                if arg[0] != "-":
                        args.append(arg)
                else:
                        del parser.rargs[:len(args)]
                        break
        if getattr(parser.values, option.dest):
                args.extend(getattr(parser.values, option.dest))
        setattr(parser.values, option.dest, args)

parser=OptionParser()
parser.add_option("-q", "--quiet",
        action="store_false", dest="verbose",
        help="be vewwy quiet (I'm hunting wabbits)")
parser.add_option("-f", "--filename",
        action="callback", callback=cb, dest="file")

(options, args) = parser.parse_args()

print options.file
print args

Единственным побочным эффектом является то, что вы получаете свои аргументы в списке вместо кортежа. Но это можно легко исправить, для моего конкретного случая использования список желателен.

10 голосов
/ 22 июня 2009

Моя ошибка: только что нашел Пример обратного вызова 6 .

8 голосов
/ 22 июня 2009

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

Этот URL-адрес документов argparse add_argument - передача nargs='*' позволяет опции принимать ноль или более аргументов, '+' позволяет принимать один или несколько аргументов и т. Д.

2 голосов
/ 22 июня 2009

Разве тебе не лучше с этим?

foo.pl --files a.txt,b.txt,c.txt --verbose
1 голос
/ 11 июня 2015

У меня недавно возникла эта проблема: я был на Python 2.6 и мне нужно было принять переменное число аргументов. Я попытался использовать решение Дейва, но обнаружил, что оно не будет работать без явного задания nargs равным 0.

def arg_list(option, opt_str, value, parser):
    args = set()
    for arg in parser.rargs:
        if arg[0] == '-':
            break
        args.add(arg)
        parser.rargs.pop(0)
    setattr(parser.values, option.dest, args)

parser=OptionParser()
parser.disable_interspersed_args()
parser.add_option("-f", "--filename", action="callback", callback=arg_list,
                  dest="file", nargs=0)

(options, args) = parser.parse_args()

Проблема заключалась в том, что по умолчанию предполагается, что новая опция, добавленная add_options, имеет nargs = 1, а когда nargs> 0 OptionParser извлекает элементы из rargs и присваивает им значение до вызова любых обратных вызовов. Таким образом, для опций, которые не определяют nargs, rargs всегда будет отключен на единицу к моменту вызова вашего обратного вызова.

Этот обратный вызов может использоваться для любого числа опций, просто для callback_args следует использовать функцию, которая будет вызываться вместо setattr.

0 голосов
/ 01 марта 2013

Вот один из способов: взять строку, генерирующую fileLst, в качестве строки, а затем использовать http://docs.python.org/2/library/glob.html, чтобы выполнить расширение, хотя это может не сработать без экранирования *

На самом деле, есть способ получше: python myprog.py -V -l 1000 /home/dominic/radar/*.json <- если это ваша командная строка </p>

parser, opts = parse_args ()

inFileLst = parser.largs

...