如何动态添加选项到optparser?

1 投票
2 回答
1293 浏览
提问于 2025-04-16 22:39

我有一个系统,可以修改哪些模块会被加载和运行。这里的“模块”不一定是Python模块,它可以是多个模块的组合。这个程序可以运行模块A和模块B。现在,我想让每个模块都能定义(添加)自己的参数。比如说,模块A想要一个-n的参数,而模块B想要一个-s的参数。但有一个共同的参数-c,是主系统需要的。请问,怎么做比较好呢?

到目前为止,我一直在使用一个单独的optparse.OptionParser实例,并在每个模块初始化时将它传递给它们。这样,模块就可以根据需要修改(添加新参数)。

2 个回答

2

你可以考虑换一个支持子解析器概念的库,比如argparse(反正optparse也要被淘汰了)。这样每个库就可以自己定义解析规则,而主程序只需要把这些规则组合起来就行了。

1

当我遇到这个问题时,我最终使用了一个从 ArgumentParser 类派生的类,这个类增加了注册回调函数的功能,这些回调函数会在参数解析完成后执行:

import argparse

class ArgumentParser(argparse.ArgumentParser):
   def __init__(self, *p, **kw):
      super(ArgumentParser, self).__init__(*p, **kw)
      self._reactions = []
   def add_reaction(self, handler):
      self._reactions.append(handler)
   def parse_known_args(self, args=None, namespace=None):
      (args, argv) = super(ArgumentParser, self).parse_known_args(args, namespace)
      for reaction in self._reactions:
         reaction(args)
      return (args, argv)

这样,解析器对象仍然需要传递给所有模块,以便注册它们的命令行选项,但模块可以“自己”对这些选项做出反应:

def arguments_parsed(args):
   if args.datafile:
      load_stuff(args.datafile)

def add_arguments(ap):
   ap.add_argument('--datafile',
         help="Load additional input data")
   ap.add_reaction(arguments_parsed)

这个方法使用了 argparse,但用 optparse 也可能实现类似的功能。

这个方法没有经过高级功能的测试,比如子解析器,可能在这些情况下无法工作,但可以很容易地扩展以支持这些功能。

撰写回答