2009-08-28 2 views
5

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

Я ищу что-то лучшее.

Моя надежда состоит в том, чтобы иметь систему, в которой я могу писать функции более или менее нормальным образом python, а затем, когда запускается скрипт, есть варианты (и текст справки), созданные из моих функций, проанализированные и выполняемые в соответствующий заказ. Кроме того, я бы очень хотел, чтобы иметь возможность создавать интерфейсы подкоманды Джанго стиля, где myscript.py install работает полностью отдельно от myscript.py remove (отдельных вариантов, помощи и т.д.)

Я нашел simon willison's optfunc и это делает много из этого, но, кажется, просто пропустить отметку - я хочу написать каждый ВАРИАНТ как функцию, а не пытаться сжать весь набор параметров в огромную строку параметров.

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

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

ответ

4

Не тратьте время на «интроспекцию».

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

  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 

Вы создаете sublcasses для 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

Спасибо, это похоже на хороший совет. –

+0

Это отлично! –

0

Библиотека WSGI Werkzeug обеспечивает Management Script Utilities, которые могут делать то, что вы хотите, или, по крайней мере, дать вам подсказку, как это сделать самоанализ самостоятельно.

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 = значение из оболочки.

Смежные вопросы