检查通过python cmd模块传递的参数

时间:2013-07-19 11:51:06

标签: python python-2.7 autocomplete cmd

这是两部分问题,请参阅下文:

  • 我需要创建某种控制台供测试人员手动运行一些命令! cmd模块是一个好方法吗?

下面是我到目前为止使用cmd模块的代码,我只是想学习,到目前为止我有两个问题:

  • 为什么自动完成功能不起作用?如果我加倍<TAB>我什么也得不到,光标就向前移动了。默认情况下不提供自动完成功能吗?

  • 我是否必须为每种方法处理错误数量的参数?我希望方法-'help'文本能够自动显示,如果方法被调用有错误的参数,或者它们应该用参数调用,而它们不是。

class InteractiveConsole(cmd.Cmd):
    """ Interactive command line """

    def __init__(self):
        cmd.Cmd.__init__(self)
        self.prompt = "=>> "
        self.intro = "Welcome to IRT console!"

    def do_hist(self, args):
        """Print a list of commands that have been entered"""
        print self._hist

    def do_exit(self, args):
        """Exits from the console"""
        return -1

    def do_help(self, args):
        """Get help on commands
           'help' or '?' with no arguments prints a list of commands for which help is available
           'help <command>' or '? <command>' gives help on <command>
        """
        # # The only reason to define this method is for the help text in the doc string
        cmd.Cmd.do_help(self, args)

    # # Override methods in Cmd object ##
    def preloop(self):
        """Initialization before prompting user for commands.
           Despite the claims in the Cmd documentaion, Cmd.preloop() is not a stub.
        """
        cmd.Cmd.preloop(self)  # # sets up command completion
        self._hist = []  # # No history yet
        self._locals = {}  # # Initialize execution namespace for user
        self._globals = {}

    def postloop(self):
        """Take care of any unfinished business.
           Despite the claims in the Cmd documentaion, Cmd.postloop() is not a stub.
        """
        cmd.Cmd.postloop(self)  # # Clean up command completion
        print "Exiting..."

    def precmd(self, line):
        """ This method is called after the line has been input but before
            it has been interpreted. If you want to modify the input line
            before execution (for example, variable substitution) do it here.
        """
        if line != '':
            self._hist += [ line.strip() ]
        return line

    def postcmd(self, stop, line):
        """If you want to stop the console, return something that evaluates to true.
           If you want to do some post command processing, do it here.
        """
        return stop

    def default(self, line):
        """Called on an input line when the command prefix is not recognized.
           In that case we execute the line as Python code.
        """
        try:
            exec(line) in self._locals, self._globals
        except Exception, e:
            print e.__class__, ":", e

    def emptyline(self):
        """Do nothing on empty input line"""
        pass





    def do_install(self, pathToBuild):
        """install [pathToBuild]
        install using the specified file"""
        if pathToBuild:
            print "installing %s" % pathToBuild
        else:
            print "<ERROR> You must specify the absolute path to a file which should be used!"


    def do_configure(self, pathToConfiguration):
        """configure [pathToConfiguration]
        configure using the specified file"""
        if pathToConfiguration:
            print "configuring %s" % pathToConfiguration
        else:
            print "<ERROR> You must specify the absolute path to a file which should be used!"

2 个答案:

答案 0 :(得分:4)

来自cmd documentation

  

可选参数 completekey 是完成键的readline名称;它默认为Tab。如果 completekey 不是None并且readline可用,则命令完成将自动完成。

您需要readline才能使标签完成工作。

命令方法只能使用一个参数,您需要在命令方法本身中解析参数。当然,如有必要,您可以调用self.do_help()self.help_<cmd>()方法。

答案 1 :(得分:0)

对于第一部分,是的,我发现cmd模块易于使用且功能强大,足以实现类似于Python内置命令提示符的CLI。

对于第二部分的第一个问题,您需要通过实现诸如complete_install(self,word,line,begindex,endindex)之类的方法来告诉模块如何完成命令行,该方法采用当前的word,line,begin,和该行的结束索引,并返回表示有效补全的字符串列表或元组。 您应该通常根据当前单词(第一个参数)来计算和过滤列表。

例如,我使用命令“ ll”来设置日志记录级别,实现如下:

def complete_ll(self, a, ln, bi, ei):
    return tuple(
        k for k in logging._nameToLevel.keys()
        if k.casefold().find(a.casefold()) >= 0)

def do_ll(self, a):
    "Set or get debug level: DL [10 .. 50 | levelName]"
    def ll():
        n = log.getEffectiveLevel()
        return f"{logging.getLevelName(n)} ({n})"
    print(ll())
    if a:
        try:
            log.setLevel(eval(a.upper(), logging._nameToLevel))
            print("Logging level changed to", ll())
        except Exception as e:
            log.exception(f"{e}, value {a}", exc_info=1)

对于第二个问题,是的,您应该检查“ do _...”方法中参数的数量,类型和有效性,在您的示例中已做过一定程度的检查。当然,如果确实有帮助,您也可以在此时调用“ help _...”方法。