有沒有一種方法可以使用模塊作爲解釋器,用於繼承cmd
的接口中的每個提示?使用argparse和cmd的Python
我希望我的cmd界面能夠解釋典型的line
參數,方法與使用可選參數-
以及位置參數來解釋在運行時在bash shell中傳遞的選項和參數相同。
有沒有一種方法可以使用模塊作爲解釋器,用於繼承cmd
的接口中的每個提示?使用argparse和cmd的Python
我希望我的cmd界面能夠解釋典型的line
參數,方法與使用可選參數-
以及位置參數來解釋在運行時在bash shell中傳遞的選項和參數相同。
好,要做到這一點的方法之一是覆蓋cmd
的default
方法,並用它與解析行,因爲沒有在你的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
如果遇到未知的命令,所以你需要重寫或猴子修補ArgumentParser
的error
方法來提高,而不是在退出異常和處理,在default
方法,以留在cmd
的命令循環中。
我建議你看看cliff,它允許你編寫可以自動使用的命令,既可以作爲和cmd
命令使用,這些命令非常簡潔。它還支持從setuptools
入口點加載命令,這允許您將命令作爲插件分發到您的應用。但請注意,cliff
使用cmd2
,這是cmd
的更強大的表親,但您可以將其替換爲cmd
,因爲cmd2
是作爲cmd
的替代替代品而開發的。
的直接的方法是創建一個解析器,並解析的情況下,你的函數內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