2008-12-12 26 views
11

什么是“干净”的方式来实现一个命令行界面,类似于Git的,例如:实现“[command] [action] [parameter]”样式的命令行界面?

git push origin/master 
git remote add origin git://example.com master 

理想的情况下也允许更灵活的分析,例如,

jump_to_folder app theappname v2 
jump_to_folder app theappname source 
jump_to_folder app theappname source v2 
jump_to_folder app theappname build v1 
jump_to_folder app theappname build 1 
jump_to_folder app theappname v2 build 

jump_to_folder是脚本名称,app是命令,theappname是“固定位置”参数,“build”和“v2”等是参数(例如,可能的参数是任何数字/以av为前缀的任何数字,或者构建/ source/tmp/config)

我可以用一系列if/else/elifs手动解析参数,但是必须有一种更优雅的方式来做到这一点?

作为一个完全理论上例如,我可以描述UI模式..

app: 
    fixed: application_name 

    optional params: 
     arg subsection: 
      "build" 
      "source" 
      "tmp" 
      "config" 

     arg version: 
      integer 
      "v" + integer 

然后解析虽然上面的架构提供的参数,并获得了词典:

>>> print schema.parse(["app", "theappname", "v1", "source"]) 
{ 
    "application_name": "theappname", 
    "params":{ 
     "subsection": "source", 
     "version":"v1" 
    } 
} 

是否这样的系统存在?如果不是,我将如何去执行这些方面的东西?从我的剧本之一

回答

10

argparse非常适合这一点,特别是"sub-commands"和位置ARGS

import argparse 


def main(): 
    arger = argparse.ArgumentParser() 

    # Arguments for top-level, e.g "subcmds.py -v" 
    arger.add_argument("-v", "--verbose", action="count", default=0) 

    subparsers = arger.add_subparsers(dest="command") 

    # Make parser for "subcmds.py info ..." 
    info_parser = subparsers.add_parser("info") 
    info_parser.add_argument("-m", "--moo", dest="moo") 

    # Make parser for "subcmds.py create ..." 
    create_parser = subparsers.add_parser("create") 
    create_parser.add_argument("name") 
    create_parser.add_argument("additional", nargs="*") 

    # Parse 
    opts = arger.parse_args() 

    # Print option object for debug 
    print opts 

    if opts.command == "info": 
     print "Info command" 
     print "--moo was %s" % opts.moo 

    elif opts.command == "create": 
     print "Creating %s" % opts.name 
     print "Additional: %s" % opts.additional 

    else: 
     # argparse will error on unexpected commands, but 
     # in case we mistype one of the elif statements... 
     raise ValueError("Unhandled command %s" % opts.command) 


if __name__ == '__main__': 
    main() 

这可以用于像这样:

$ python subcmds.py create myapp v1 blah 
Namespace(additional=['v1', 'blah'], command='create', name='myapp', verbose=0) 
Creating myapp 
Additional: ['v1', 'blah'] 
$ python subcmds.py info --moo 
usage: subcmds.py info [-h] [-m MOO] 
subcmds.py info: error: argument -m/--moo: expected one argument 
$ python subcmds.py info --moo 1 
Namespace(command='info', moo='1', verbose=0) 
Info command 
--moo was 1 
2

直:

import sys 

def prog1_func1_act1(): print "pfa1" 
def prog2_func2_act2(): print "pfa2" 

commands = { 
    "prog1 func1 act1": prog1_func1_act1, 
    "prog2 func2 act2": prog2_func2_act2 
} 

try: 
    commands[" ".join(sys.argv[1:])]() 
except KeyError: 
    print "Usage: ", commands.keys() 

这是一个非常快速和肮脏的解决方案,但我使用的伟大工程。如果我将它清理一下,我可能会添加argparse来解析位置和关键字参数。

+0

问题这是参数是固定的..例如,你不能轻易拥有一个“v001”..“v102”选项,短于每个组合创建一个键.. – dbr 2008-12-12 11:34:40

+0

是的,我知道,这就是为什么我提到了argparse。例如,如果您的“命令”和“操作”相对较少,但参数很多,则可以使用我使用的方法分派到特定的操作,然后将参数(和可选的关键字参数)传递到使用argparse的脚本。 – kmelva 2008-12-12 11:40:46

+0

加上,你可以添加一个元命令'help'来打印命令的内容并显示他们的.__ doc__字符串 – pjz 2008-12-12 14:52:26

1

Python有一个解析命令行选项的模块,optparse

9

cmd模块可能对此很好。

例子:

import cmd 

class Calc(cmd.Cmd): 
    def do_add(self, arg): 
     print sum(map(int, arg.split())) 

if __name__ == '__main__': 
    Calc().cmdloop() 

运行:

$python calc.py 
(Cmd) add 4 5 
9 
(Cmd) help 

Undocumented commands: 
====================== 
add help 

(Cmd) 

见获取更多信息Python docsPyMOTW site

0

这是我的建议。

  1. 稍微改变语法。

  2. 使用optparse。

在理想情况下也允许更灵活的解析,例如,

jump_to_folder -n theappname -v2 cmd 
jump_to_folder -n theappname cmd source 
jump_to_folder -n theappname -v2 cmd source 
jump_to_folder -n theappname -v1 cmd build 
jump_to_folder -n theappname -1 cmd build 
jump_to_folder -n theappname -v2 cmd build 

然后,你必须1个或2 ARGS:命令总是第一个参数。这是可选的参数总是第二个参数。

其他一切都是选项,没有特别的顺序。