4

我有以下示例设置:

|-- 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 实例并引发错误?

4

2 回答 2

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()
于 2011-10-24T06:33:27.597 回答
0

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

模块.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 ) 

主文件

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 --帮助

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
于 2011-10-25T02:25:57.853 回答