2008-12-12 56 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:命令總是第一個參數。這是可選的參數總是第二個參數。

其他一切都是選項,沒有特別的順序。