несколько вызовов OptionParser.parse_args () в рамках одного и того же выполнения Python - PullRequest
4 голосов
/ 24 октября 2011

У меня есть следующий пример настройки:

|-- main_script.py
`-- module
    |-- __init__.py
    `-- submodule.py

где содержимое main_script:

import optparse
import module

parser = optparse.OptionParser()
group = optparse.OptionGroup("submodules options")
group.add_option("","--main_script.bar", dest="bar", action="store_true")
parser.add_option_group(group)

opts,args = parser.parse_args()

if opts.bar:
    print ("Bar")

и содержимое submodule.py:

import optparse
parser = optparse.OptionParser()
group = optparse.OptionGroup(parser, "submodules options")
group.add_option("","--module.submodule.foo", dest="foo", action="store_true")
parser.add_option_group(group)

opts,args = parser.parse_args()

if opts.foo:
    print ("Foo")

Поскольку main_script импортирует субмодуль, вызывается parse_args из субмодуля.Есть ли способ объединить эти экземпляры OptionParser и вызвать ошибку, если есть конфликты параметров?

Ответы [ 2 ]

2 голосов
/ 24 октября 2011

Самый простой способ - разбить вашу логику на функции. Вы не должны выполнять логику в глобальной области видимости модуля, а использовать конструкцию оболочки if name == "__main__".

Вы можете определить функцию add_options(parser) для каждого модуля, которая должна определять опции, и вызвать ее на корневом уровне перед вызовом parse_args:

import optparse
import submodule

def add_options(parser):
    parser.add_option(...)

def main():
    parser = optparse.OptionParser()
    add_options(parser)
    submodule.add_options(parser)
    opts, args = parser.parse_args()
    #...

if __main__ == "__main__":
    main()
0 голосов
/ 25 октября 2011

В попытке решить эту проблему извне - у меня есть первоначальная реализация, которая исправляет модуль optparse, заменяя класс OptionParser подклассом OptionParser и перегружая метод parse_args +, выставляя новый метод delayed_parse_args. Я делюсь фрагментами этого решения на тот случай, если кто-нибудь найдет его полезным или сможет улучшить его.

optparse_patch.py ​​

import optparse

def patch_opt_parser():
    optparse.stashed_parsers = {}

    class OptionParserEx(optparse.OptionParser):
        def delayed_parse_args(self, callback):
            optparse.stashed_parsers[self] = callback

        def parse_args(self, args=None, values=None):
            for parser, callback in getattr(optparse,"stashed_parsers").items():
                # add all the option_list & option_groups from the individual
                # parsers in stashed_parsers to `self`
            for parser, callback in getattr(optparse,"stashed_parsers").items():
                # update `parser` to inherit the option_lists and option_groups from 
                # self. then ....
                _o, _a = optparse._OptionParser.parse_args( parser, args, values )
                callback( _o, _a t)
            return getattr(optparse,"_OptionParser").parse_args(self, args, values)

    optparse._OptionParser = optparse.OptionParser
    optparse.OptionParser = OptionParserEx

patch_opt_parser()

Это позволяет подмодулям «спрятать» свои ожидаемые параметры и оценить параметры командной строки на более позднем этапе, когда клиент модуля фактически предоставляет OptionParser и вызывает метод parse_args для своего собственного OptionParser. Пример такого варианта использования следующий:

module.py

import optparse_patch
import optparse
parser = optparse.OptionParser()
group = optparse.OptionGroup(parser, "module options")
group.add_option("-f", dest="flip", action="store_true")
parser.add_option_group(group)
def cli_callback ( opts, args ):
    if opts.flip: 
        print "flip"
opts, args = parser.delayed_parse_args ( cli_callback ) 

main.py

import module
import optparse


myparser = optparse.OptionParser()
mygroup = optparse.OptionGroup(myparser, "main options")
mygroup.add_option("-j", dest="jump", action="store_true")
myparser.add_option_group(mygroup)
opts, args = myparser.parse_args()
if opts.jump:
     print "jump"

вызов программы main.py приводит к следующим выводам:

python main.py --help

Usage: main.py [options]

Options:
  -h, --help  show this help message and exit

  module options:
    -f        

  main options:
    -j        

python main.py -j -f

flip
jump
...