Модуль Python OptionParser – несколько записей одной и той же переменной?

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

#!/usr/bin/python

import sys
from optparse import OptionParser
...
parser.add_option("-s", "--server", dest="server", metavar="SERVER", type="string", 
                  help="server(s) to gather stats [default: localhost]")
...

моя ЦЕЛЬ - сделать что-то вроде

#test.py -s server1 -s server2

и он каким-то образом добавил бы оба этих значения в объект options.server, чтобы я мог перебирать их, независимо от того, имеют ли они 1 значение или 10.

Любые мысли/помощь приветствуются. Спасибо.


person jduncan    schedule 03.05.2010    source источник


Ответы (5)


Да, это можно сделать с помощью 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

person Richard Gomes    schedule 01.05.2012

Вы можете попробовать проверить argparse. Он предоставляет параметр «nargs», означающий, что вы сможете что-то сделать вместе

#test.py -s server1 server2

Я знаю, что это не совсем то, что требовалось, но это может быть достойный компромисс без особых хлопот. :)

person Juho Vepsäläinen    schedule 03.05.2010

Может быть проще принять список серверов, разделенных запятыми:

# test.py -s server1,server2

и разделите значение в вашем скрипте.

person harto    schedule 03.05.2010

Вот известный рабочий пример (от http://docs.python.org/library/email-examples.html):

parser.add_option('-r', '--recipient',
                  type='string', action='append', metavar='RECIPIENT',
                  default=[], dest='recipients',
                  help='A To: header value (at least one required)')

Я думаю, что использование что-то вроде:

python script.py -r [email protected] -r [email protected] -r [email protected]
person jGc    schedule 07.04.2012

person    schedule
comment
Я тоже думал, что это сработает. Однако я получаю эту ошибку: AttributeError: объект 'str' не имеет атрибута 'append', когда я даю параметру строки это действие. - person jduncan; 03.05.2010
comment
@jduncan: ты уверен? Я только что попробовал, и снова все работает так, как ожидалось. - person mg.; 03.05.2010
comment
Это не работает для меня (Python 2.6), если я не укажу никаких параметров - options.test имеет значение None и не может быть перечислено - person Marius Gedminas; 03.05.2010
comment
Кроме этого, этот код работает с Python 2.4, 2.5 и 2.6. - person Marius Gedminas; 03.05.2010
comment
@jduncan: я могу воспроизвести ошибку, если сделаю parser.add_option(..., default='a_string', action='append'), но это неправильно. На самом деле, если вы сделаете это и не предоставите опцию, вы в конечном итоге переберете все символы. Кроме того, указание чего-либо будет только добавлено, поэтому вы никогда не сможете переопределить сервер по умолчанию. Не делай этого; если вам нужно значение по умолчанию, сделайте enumerate(options.test or ['default']). - person Marius Gedminas; 03.05.2010
comment
Re: итерация, установка default=[] в вызове add_option заставляет его работать без параметров или с несколькими параметрами. - person eternicode; 18.03.2011