命令行arg通过内省解析

时间:2009-08-28 06:58:05

标签: python command-line parsing

我正在开发一个管理脚本,通过大量的命令行选项完成相当大的工作。脚本的前几次迭代使用optparse来收集用户输入,然后向下运行页面,以适当的顺序测试每个选项的值,并在必要时执行操作。这导致了一个非常难以阅读和维护的代码丛林。

我正在寻找更好的东西。

我希望有一个系统,我可以用或多或少的正常python方式编写函数,然后在运行脚本时,从我的函数生成选项(和帮助文本),解析并执行相应的订购。另外,我真的希望能够构建django风格的子命令接口,其中myscript.py installmyscript.py remove完全分开工作(单独的选项,帮助等)。

我发现了simon willison's optfunc并且它做了很多,但似乎只是错过了标记 - 我想把每个OPTION写成一个函数,而不是试图将整个选项集压缩成一个巨大的一系列选项。

我想象一个体系结构涉及一组主要函数的类,以及每个与命令行中特定选项对应的类的定义方法。这种结构的优点是每个选项都位于它修改的功能代码附近,从而简化了维护。我不知道如何处理的事情是命令的排序,因为类方法的排序不是确定性的。

在我重新发明轮子之前:还有其他现有的代码行为类似吗?其他容易修改的东西?问这个问题已经澄清了我自己对什么是好的想法,但是对于为什么这是一个糟糕的想法或者它应该如何工作的反馈将是受欢迎的。

2 个答案:

答案 0 :(得分:4)

不要在“内省”上浪费时间。

每个“命令”或“选项”都是具有两组方法函数或属性的对象。

  1. 提供设置信息以进行optparse。

  2. 实际上做的工作。

  3. 这是所有命令的超类

    class Command( object ):
        name= "name"
        def setup_opts( self, parser ):
            """Add any options to the parser that this command needs."""
            pass
        def execute( self, context, options, args ):
            """Execute the command in some application context with some options and args."""
            raise NotImplemented
    

    您可以为InstallRemove以及您需要的所有其他命令创建子图块。

    您的整体应用程序看起来像这样。

    commands = [ 
        Install(),
        Remove(),
    ]
    def main():
        parser= optparse.OptionParser()
        for c in commands:
            c.setup_opts( parser )
        options, args = parser.parse()
        command= None
        for c in commands:
            if c.name.startswith(args[0].lower()):
                command= c
                break
        if command:
            status= command.execute( context, options, args[1:] )
        else:
            logger.error( "Command %r is unknown", args[0] )
            status= 2
        sys.exit( status )
    

答案 1 :(得分:0)

WSGI库werkzeug提供了 Management Script Utilities ,可以做你想做的事,或者至少给你一个如何自己进行内省的提示。

from werkzeug import script

# actions go here
def action_test():
    "sample with no args"
    pass

def action_foo(name=2, value="test"):
    "do some foo"
    pass

if __name__ == '__main__':
    script.run()

这将生成以下帮助信息:

$ python /tmp/test.py --help
usage: test.py <action> [<options>]
       test.py --help

actions:
  foo:
    do some foo

    --name                        integer   2
    --value                       string    test

  test:
    sample with no args

一个动作是同一个模块中的一个函数,以“action_”开头,它带有一些参数,其中每个参数都有一个默认值。默认值的类型指定参数的类型。

然后可以通过位置或使用shell中的--name = value传递参数。