在同一个python执行中多次调用OptionParser.parse_args()

时间:2011-10-24 06:20:57

标签: python optionparser

我有以下示例设置:

|-- 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 个答案:

答案 0 :(得分:2)

最简单的方法是将逻辑分解为函数。您不应该首先在全局模块范围内执行逻辑,而是使用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()

答案 1 :(得分:0)

试图从外部解决这个问题 - 我有一个初始实现,通过用OptionParser的子类替换OptionParser类来修补optparse模块,并重载parse_args方法+暴露一个新的delayed_pa​​rse_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并在其自己的OptionParser上调用parse_args方法时,在稍后阶段评估命令行选项。这种用例的一个例子如下:

<强> 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