代码之家  ›  专栏  ›  技术社区  ›  Paul McMillan

通过自省进行命令行arg解析

  •  5
  • Paul McMillan  · 技术社区  · 15 年前

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

    我在找更好的东西。

    我希望有一个系统,在这个系统中,我可以或多或少地用普通的Python方式编写函数,然后当脚本运行时,让我的函数生成选项(和帮助文本),并按适当的顺序进行解析和执行。此外,我真的希望能够构建django风格的子命令接口,在 myscript.py install 完全独立于 myscript.py remove (单独选项、帮助等)

    我找到了 simon willison's optfunc 它做了很多这方面的工作,但似乎忽略了我想把每个选项都写为函数的标记,而不是试图将整个选项集压缩成一个巨大的选项字符串。

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

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

    2 回复  |  直到 15 年前
        1
  •  4
  •   S.Lott    15 年前

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

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

    1. 向optparse提供设置信息。

    2. 实际上,做这项工作。

    这是所有命令的超类

    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
    

    为创建子类 Install Remove 以及其他你需要的命令。

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

    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 )
    
        2
  •  0
  •   Srikanth    15 年前

    wrkzeug提供的wsgi库 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_uuu”开头的一个函数,它接受许多参数,其中每个参数都有一个默认值。默认值的类型指定参数的类型。

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