【问题标题】:Python: parse commandlinePython:解析命令行
【发布时间】:2012-05-09 00:02:06
【问题描述】:

我正在用 python 编写一个 CLI 应用程序,它通过一种相当复杂的命令行语言来使用。这个想法与 find(1) 非常相似,可以说具有相同的属性。

目前,解析器完全是使用手工制作的 EBNF 描述语言手写的。问题是这种语言使用起来非常尴尬,因为我必须将所有东西都写成 python 结构。我也觉得我的程序因为解析的原因还是太臃肿了。

是否有任何库具有易用性和用于命令行解析的真实描述语言(作为字符串/文档输入)?从语法树中,我想直接将每个项目映射到一个类实例。自然,我不想要分词器,或者至少分词器必须直接从命令行参数映射到令牌。

感谢所有建议!

更新:我的程序的重点是生成对象并将它们通过任意数量的过滤器(可能是不纯/有效的操作),这些过滤器可能会或可能不会再次输出对象,甚至可能另一种类型的输出对象。总体思路显然是从 find(1) 中收集到的。一个示例命令行是:

~/picdb.py -sqlselect 'select * from pics where dirname like "testdir%"' -tagged JoSo  -updateFromFile [ -resx +300 -or -resX +200 -resY +500 ] -printfXml '<jpegfile><src>%fp</src><DateTimeOriginal>%ed</DateTimeOriginal><Manufacturer>%eM</Manufacturer><Model>%em</Model></jpegfile>%NL'

【问题讨论】:

  • argparse (python 2.7+) 能满足您的需求吗?
  • 除了@Aufwind 的评论——对于用户argparse,您不需要需要拥有python 2.7 或更新版本。它适用于旧版本的 python - 你只需要自己安装(而不是包含在标准库中)。
  • 我认为如果你描述了你的命令行(或者至少给出了一个或两个例子),我们也许可以看看这是否是 argparse/optparse 的候选者......
  • @mgilson:谢谢,好点子,我会更新我的帖子并期待更好的答案,而不仅仅是反问:)

标签: python parsing


【解决方案1】:

这是一个非常棘手的问题...您可以很容易地使用 argparse 将操作“绑定”到命令行参数(例如,创建一个类,对先前创建的类进行操作...)。这是一个愚蠢的例子......(参数--foo创建一个对象,参数--bar修改由--foo创建的对象)。

from argparse import ArgumentParser,Action

class Foo(object):
    def __init__(self,*args):
        self.args=args
    def __str__(self):
        return str(self.args)

class FooAction(Action):
    def __call__(self,parser,namespace,values,option_string=None):
        setattr(namespace,self.dest,Foo(*values))  #Add Foo to the options...
class BarAction(Action):
    def __call__(self,parser,namespace,values,option_string=None):
        FooObj=getattr(namespace,'foo')  #raises an error if foo isn't in namespace...
                                         #In this way, BarAction is like a filter on the
                                         #object created by foo.
        FooObj.args=tuple(list(FooObj.args)+list(values)) #append to the list of args.

parser=ArgumentParser()
parser.add_argument('--foo',nargs='*',action=FooAction,help="Foo!")
parser.add_argument('--bar',nargs='*',action=BarAction,help="Bar! : Must be used after --foo")

namespace=parser.parse_args("--foo Hello World --bar Nice Day".split())
print (namespace)
print (namespace.foo)

但是,这与您的有点不同,因为 -argument 无法使用 argparse,只有 -a--argument。这对你来说可能已经是一个交易破坏者了,我不确定......

下一个困难是处理括号...[]。如果您可以将它们视为不同命令行选项的参数,则可能没问题...您可能可以设置第二个解析器来解析内部部分-但我以前从未尝试过类似的东西.. .(如果其他人对如何处理括号有任何想法,我很想听听他们的意见)。

optparsegetopt 而言,我很确定你可以用它们做的任何事情,你都可以用argparse 做,这就是我将它们排除在讨论之外的原因。

【讨论】:

  • 非常感谢您的努力。这意味着我可能会继续使用我的手工解决方案。
【解决方案2】:

您至少可以尝试三个模块; argparseoptparse(在 2.7 中已弃用)和 getopt。请参阅 Python 标准库手册的第 15 章。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-07
    • 2016-10-28
    • 1970-01-01
    • 1970-01-01
    • 2010-11-27
    • 2020-01-25
    • 2020-01-01
    • 1970-01-01
    相关资源
    最近更新 更多