анализ командной строки с помощью самоанализа - PullRequest
5 голосов
/ 28 августа 2009

Я разрабатываю сценарий управления, который выполняет довольно большой объем работы с помощью множества параметров командной строки. Первые несколько итераций скрипта использовали optparse для сбора пользовательского ввода, а затем просто бегали по странице, проверяя значение каждого параметра в соответствующем порядке и выполняя действие при необходимости. Это привело к джунглям кода, которые действительно трудно читать и поддерживать.

Я ищу что-нибудь получше.

Я надеюсь, что у меня будет система, в которой я смогу писать функции более или менее обычным образом на Python, а затем, когда скрипт будет запущен, иметь параметры (и текст справки), сгенерированные из моих функций, проанализированные и выполненные в соответствующих порядок. Кроме того, я ДЕЙСТВИТЕЛЬНО хотел бы иметь возможность создавать интерфейсы подкоманд в стиле django, где myscript.py install работает полностью отдельно от myscript.py remove (отдельные опции, помощь и т. Д.)

Я нашел optfunc * Саймона Уилсона , и он многое делает, но, похоже, просто пропускает отметку - я хочу записать каждое OPTION как функцию, а не пытаться сжать весь параметр установить в огромную строку вариантов.

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

Прежде чем я начну заново изобретать колесо: существуют ли какие-либо другие биты кода, которые ведут себя аналогично? Другие вещи, которые было бы легко изменить? Задавая вопрос, я прояснил свое собственное мнение о том, что было бы неплохо, но отзывы о том, почему это ужасная идея или как она должна работать, приветствуются.

Ответы [ 2 ]

4 голосов
/ 28 августа 2009

Не тратьте время на «самоанализ».

Каждая «Команда» или «Опция» является объектом с двумя наборами функций или атрибутов метода.

  1. Предоставить информацию о настройке optparse.

  2. На самом деле делать работу.

Вот суперкласс для всех команд

class Command( object ):
    name= "name"
    def setup_opts( self, parser ):
        """Add any options to the parser that this command needs."""
        pass
    def execute( self, context, options, args ):
        """Execute the command in some application context with some options and args."""
        raise NotImplemented

Вы создаете подкадры для Install и Remove и для любой другой необходимой вам команды.

Ваше общее приложение выглядит примерно так.

commands = [ 
    Install(),
    Remove(),
]
def main():
    parser= optparse.OptionParser()
    for c in commands:
        c.setup_opts( parser )
    options, args = parser.parse()
    command= None
    for c in commands:
        if c.name.startswith(args[0].lower()):
            command= c
            break
    if command:
        status= command.execute( context, options, args[1:] )
    else:
        logger.error( "Command %r is unknown", args[0] )
        status= 2
    sys.exit( status )
0 голосов
/ 28 августа 2009

Библиотека WSGI werkzeug предоставляет Утилиты сценария управления , которые могут делать то, что вы хотите, или, по крайней мере, подсказывать вам, как сделать самоанализ самостоятельно.

from werkzeug import script

# actions go here
def action_test():
    "sample with no args"
    pass

def action_foo(name=2, value="test"):
    "do some foo"
    pass

if __name__ == '__main__':
    script.run()

Который сгенерирует следующее сообщение справки:

$ python /tmp/test.py --help
usage: test.py <action> [<options>]
       test.py --help

actions:
  foo:
    do some foo

    --name                        integer   2
    --value                       string    test

  test:
    sample with no args

Действие - это функция в том же модуле, начинающаяся с «action_», которая принимает ряд аргументов, где каждый аргумент имеет значение по умолчанию. Тип значения по умолчанию указывает тип аргумента.

Затем аргументы можно передать по позиции или с помощью --name = value из оболочки.

...