【问题标题】:gem/git-style command line arguments in PythonPython 中的 gem/git 风格的命令行参数
【发布时间】:2018-08-28 20:47:01
【问题描述】:

是否有用于执行 gem/git-style 命令行参数的 Python 模块?我所说的 gem/git 风格是:

$ ./MyApp.py
The most commonly used MyApp commands are:
  add        Add file contents to the index
  bisect     Find by binary search the change that introduced a bug
  branch     List, create, or delete branches
  checkout   Checkout a branch or paths to the working tree
  ...

$ ./MyApp.py branch
  * current-branch
    master

没有参数,输出告诉你如何继续。还有一个特殊的“帮助”命令:

$ ./MyApp.py help branch

这将为您提供有关“分支”命令的更深入提示。

编辑: 我的意思是它会为您打印使用情况,以无效输入退出,根据您的 CLI 规范运行您的函数。类似于命令行的“URL 映射器”。

【问题讨论】:

    标签: python command-line-interface


    【解决方案1】:

    是的,argparseadd_subparsers()

    Sub-commands 部分对此进行了很好的解释。

    从那里复制其中一个示例:

    >>> parser = argparse.ArgumentParser()
    >>> subparsers = parser.add_subparsers()
    >>> checkout = subparsers.add_parser('checkout', aliases=['co'])
    >>> checkout.add_argument('foo')
    >>> parser.parse_args(['checkout', 'bar'])
    Namespace(foo='bar')
    

    编辑: 不幸的是,没有自生成的特殊help 命令,但您可以像通常那样使用-h--help 获得详细的帮助消息(您似乎想要的)命令后:

    $ ./MyApp.py branch --help
    

    我所说的冗长并不是说它就像一个手册页,它就像其他所有 --help 类型的帮助:列出所有参数等...

    例子:

    >>> parser = argparse.ArgumentParser()
    >>> subparsers = parser.add_subparsers(description='Sub description')
    >>> checkout = subparsers.add_parser('checkout', description='Checkout description')
    >>> checkout.add_argument('foo', help='This is the foo help')
    >>> parser.parse_args(['checkout', '--help'])
    usage:  checkout [-h] foo
    
    Checkout description
    
    positional arguments:
      foo         This is the foo help
    
    optional arguments:
      -h, --help  show this help message and exit
    

    如果需要,应该很容易实现重定向到--helphelp 命令。

    【讨论】:

    • 值得指出的是,subparsers.add_parser()aliases 关键字对于 Python 3 来说是新的,在 Python 2.7 中不可用。
    • 小心 argparse:一旦你开始添加嵌套的子解析器,事情就会变得非常混乱。例如:bugs.python.org/issue9253
    • 伟大的click 包提供了开箱即用的功能!查看复杂教程here
    • Note that the object returned by parse_args() will only contain attributes for the main parser and the subparser that was selected by the command line (and not any other subparsers). So in the example above, when the a command is specified, only the foo and bar attributes are present, and when the b command is specified, only the foo and baz attributes are present. 你知道有什么办法可以让我检测到哪个子解析器被调用了吗?
    • 没关系。如果您想检查调用了哪个子解析器,请将 dest 选项添加到您的 add_subparsers() 调用中:stackoverflow.com/a/9286586
    【解决方案2】:

    获得 gem/git 风格的“帮助”行为的合理技巧(我只是为了我正在做的事情而写这个):

    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers(dest='sub_commands')
    parser_branch = subparsers.add_parser('branch', description='list of branches')
    parser_help = subparsers.add_parser('help')
    parser_help.add_argument('command', nargs="?", default=None)
    
    # I can't find a legitimate way to set a default subparser in the docs
    #   If you know of one, please let me know!
    if len(sys.argv) < 2:
        sys.argv.append('--help')
    
    parsed = parser.parse_args()
    
    if parsed.sub_commands == "help":
        if not parsed.command:
            parser.parse_args(['--help'])
        else:
            parser.parse_args([parsed.command, '--help'])
    

    argparse 绝对比我遇到的 optparse 和其他 python 解决方案更上一层楼。但是 IMO 处理 args 的 gem/git 风格只是一种更合乎逻辑和更安全的做事方式,因此不支持它很烦人。

    【讨论】:

      【解决方案3】:

      我想做一些类似于 git 命令的事情,我会根据其中一个命令行选项加载第二个脚本,并让该脚本填充更多命令行选项,并让帮助工作。

      我可以通过禁用帮助选项、解析已知参数、添加更多参数、重新启用帮助选项,然后解析其余参数来做到这一点。

      这是我想出来的。

      import argparse 
      #Note add_help=False
      arg_parser = argparse.ArgumentParser(description='Add more arguments after parsing.',add_help=False)
      arg_parser.add_argument('MODE',  default='default',type=str, help='What commands to use')
      
      
      args = arg_parser.parse_known_args()[0]
      
      if args.MODE == 'branch':
         arg_parser.add_argument('-d', '--delete', default='Delete a branch')
         arg_parser.add_argument('-m', '--move', default='move a branch')
      elif args.MODE == 'clone' :
         arg_parser.add_argument('--local', '-l')
         arg_parser.add_argument('--shared')
      
      #Finally re-enable the help option, and reparse the arguments
      arg_parser.add_argument(
                  '-h', '--help',
                  action='help', default=argparse.SUPPRESS,
                  help=argparse._('show this help message and exit'))
      
      args = arg_parser.parse_args()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-12-17
        • 1970-01-01
        • 2014-05-22
        • 1970-01-01
        • 1970-01-01
        • 2012-02-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多