2012-10-05 37 views
4

有沒有一種方法可以使用​​模塊作爲解釋器,用於繼承cmd的接口中的每個提示?使用argparse和cmd的Python

我希望我的cmd界面能夠解釋典型的line參數,方法與使用可選參數-以及位置參數來解釋在運行時在bash shell中傳遞的選項和參數相同。

回答

3

好,要做到這一點的方法之一是覆蓋cmddefault方法,並用它與​​解析行,因爲沒有在你的cmd.Cmd子do_方法的所有命令都將落空使用default方法。請注意0​​之前的附加_,以避免它被用作cmd的命令。

import argparse 
import cmd 
import shlex 

class TestCLI(cmd.Cmd): 

    def __init__(self, **kwargs): 
     cmd.Cmd.__init__(self, **kwargs) 

     self.parser = argparse.ArgumentParser() 
     subparsers = self.parser.add_subparsers() 
     test_parser = subparsers.add_parser("test") 
     test_parser.add_argument("--foo", default="Hello") 
     test_parser.add_argument("--bar", default="World") 
     test_parser.set_defaults(func=self._do_test) 

    def _do_test(self, args): 
     print args.foo, args.bar 

    def default(self, line): 
     args = self.parser.parse_args(shlex.split(line)) 
     if hasattr(args, 'func'): 
      args.func(args) 
     else: 
      cmd.Cmd.default(self, line) 

test = TestCLI() 
test.cmdloop() 

​​做了sys.exit如果遇到未知的命令,所以你需要重寫或猴子修補ArgumentParsererror方法來提高,而不是在退出異常和處理,在default方法,以留在cmd的命令循環中。

我建議你看看cliff,它允許你編寫可以自動使用的命令,既可以作爲​​和cmd命令使用,這些命令非常簡潔。它還支持從setuptools入口點加載命令,這允許您將命令作爲插件分發到您的應用。但請注意,cliff使用cmd2,這是cmd的更強大的表親,但您可以將其替換爲cmd,因爲cmd2是作爲cmd的替代替代品而開發的。

1

的直接的方法是創建一個​​解析器,並解析的情況下,你的函數內line.split()expect荷蘭國際集團SystemExit無效提供參數(parse_args()電話sys.exit()當它發現無效的參數)。

class TestInterface(cmd.Cmd): 

    __test1_parser = argparse.ArgumentParser(prog="test1") 
    __test1_parser.add_argument('--bar', help="bar help") 

    def help_test1(self): self.__test1_parser.print_help() 

    def do_test1(self, line): 
     try: 
      parsed = self.__test1_parser.parse_args(line.split()) 
     except SystemExit: 
      return 
     print("Test1...") 
     print(parsed) 

如果無效的參數傳遞,parse_args()將打印錯誤,程序將返回到界面,而無需退出。

(Cmd) test1 --unk 
usage: test1 [-h] [--bar BAR] 
test1: error: unrecognized arguments: --unk 
(Cmd) 

其他的一切應該工作一樣經常​​使用的情況下,還保持所有的cmd的功能(幫助信息,功能列表等)

來源:https://groups.google.com/forum/#!topic/argparse-users/7QRPlG97cak


另一種簡化上述設置的方法是使用下面的修飾器:

class ArgparseCmdWrapper: 
    def __init__(self, parser): 
     """Init decorator with an argparse parser to be used in parsing cmd-line options""" 
     self.parser = parser 
     self.help_msg = "" 

    def __call__(self, f): 
     """Decorate 'f' to parse 'line' and pass options to decorated function""" 
     if not self.parser: # If no parser was passed to the decorator, get it from 'f' 
      self.parser = f(None, None, None, True) 

     def wrapped_f(*args): 
      line = args[1].split() 
      try: 
       parsed = self.parser.parse_args(line) 
      except SystemExit: 
       return 
      f(*args, parsed=parsed) 

     wrapped_f.__doc__ = self.__get_help(self.parser) 
     return wrapped_f 

    @staticmethod 
    def __get_help(parser): 
     """Get and return help message from 'parser.print_help()'""" 
     f = tempfile.SpooledTemporaryFile(max_size=2048) 
     parser.print_help(file=f) 
     f.seek(0) 
     return f.read().rstrip() 

它使得定義附加命令變得更簡單,在這裏他們需要額外的parsed參數,其中包含成功的parse_args()的結果。如果有任何無效的參數,該函數從不輸入,一切都由裝飾器處理。

__test2_parser = argparse.ArgumentParser(prog="test2") 
__test2_parser.add_argument('--foo', help="foo help") 

@WrapperCmdLineArgParser(parser=__test2_parser) 
def do_test2(self, line, parsed): 
    print("Test2...") 
    print(parsed) 

一切工作作爲最初的例子,包括​​生成的幫助信息 - 而不需要定義一個help_command()功能。

來源:https://codereview.stackexchange.com/questions/134333/using-argparse-module-within-cmd-interface