(这是一个简化的问题。)我正在编写一个涉及Python组件的API。这些可能是功能,但具体来说,让我们说他们是对象。我希望能够从命令行解析各种组件的选项。使用Python/argparse创建可组合/分层命令行分析器
from argparse import ArgumentParser
class Foo(object):
def __init__(self, foo_options):
"""do stuff with options"""
"""..."""
class Bar(object):
def __init__(sef, bar_options):
"""..."""
def foo_parser():
"""(could also be a Foo method)"""
p = ArgumentParser()
p.add_argument('--option1')
#...
return p
def bar_parser(): "..."
但现在我希望能够建立更大的组件:
def larger_component(options):
f1 = Foo(options.foo1)
f2 = Foo(options.foo2)
b = Bar(options.bar)
# ... do stuff with these pieces
精细。但是如何编写适当的解析器?我们不妨这样的事情:
def larger_parser(): # probably need to take some prefix/ns arguments
# general options to be overridden by p1, p2
# (this could be done automagically or by hand in `larger_component`):
p = foo_parser(prefix=None, namespace='foo')
p1 = foo_parser(prefix='first-foo-', namespace='foo1')
p2 = foo_parser(prefix='second-foo-', namespace='foo2')
b = bar_parser()
# (you wouldn't actually specify the prefix/namespace twice:)
return combine_parsers([(p1, namespace='foo1', prefix='first-foo-'),
(p2,...),p,b])
larger_component(larger_parser().parse_args())
# CLI should accept --foo1-option1, --foo2-option1, --option1 (*)
这看起来有点像的parents
功能,如果你忘了我们想要的前缀(以便能够添加相同类型的多个解析器) 和可能命名空间(以便我们可以构建树形结构的命名空间以反映组件的结构)。
当然,我们希望large_component和larger_parser以相同的方式组合,并且传递给某个组件的名称空间对象应始终具有相同的内部形状/命名结构。
麻烦似乎是在API基本上是关于变异的你分析器,但查询它们是比较困难的 - 如果你直接打开一个 数据类型为解析器,你可以只走这些对象。如果用户编写了一堆函数以手动添加参数给解析器,但是每个add_argument
调用都必须带一个前缀,并且整个事情变得非常难以理解,并且可能不可组合,所以我设法破解了某些有些作用。 (你可以通过复制内部数据结构的某些部分来对此进行抽象...)。我也试图子类parser
和group
对象...
你可以想象这可能使用更多的代数CLI-解析API是可能的,但我不认为重写这里是一个很好的解决方案。
有没有一种已知的/直接的方法来做到这一点?
你能证明你想使用一个命令行的一个例子?起初,它看起来像你想'subparsers'(这是argparse默认提供的),但我不能100%确定它是否适合你的需求。 – mgilson
'subparsers'似乎是关于解析器(解析器A,或B或...)的“总和”,而我想要一个“产品”(所有选项可同时使用)。 – Fixnum
有关示例,请参阅问题中用'(*)'指示的行。 – Fixnum