Sunday, October 3, 2010

cmd

我们先看看下面简单的例子
#!/usr/bin/env python

import readline
import cmd
import sys

histfile='test06.hist'

class testcmd( cmd.Cmd ):
    def emptyline( self ):
        print 'empty line entered'
    def do_ls( self, str ):
        '''list the content of a directory'''
        print 'ls ' + str
    def preloop( self ):
        print 'welcome to our testing shell'

if __name__ == '__main__':
    try:
        readline.parse_and_bind( 'Tab: complete' )
        readline.read_history_file( histfile )
    except IOError:
        pass
    import atexit
    atexit.register( readline.write_history_file, histfile )

    mycmd = testcmd( 'Tab', sys.stdin, sys.stdout )
    mycmd.prompt = '> '
    try:
        mycmd.cmdloop()
    except KeyboardInterrupt:
        print 'exiting...'
        sys.exit(0)
当然这是一个非常简单的例子,大致展示了如何使用 cmd 做一个基本的命令行接口。这里使用了 readline 模块,用于记录命令历史,另外使用了 atexit 保证在退出的时候写入历史文件。使用 cmd 的基本方法可以看出就是继承 cmd.Cmd 类,重载其方法,对起某些成员进行赋值,这里我们重载了 Cmd.emptyline() 方法,使得用户没有输入的时候显示一行废话。

下面我们将仔细看看 cmd.Cmd 其他有用的方法。
  • cmd.Cmd 最重要的就是 Cmd.cmdloop(),这个循环开始会调用 Cmd.preloop(),结束会调用 Cmd.postloop();
  • 进入循环后,首先会显示 Cmd.prompt,等候用户输入,如果用户输入的命令是我们已经定义(见下面)的,则会执行 do_* 函数;如果是以 ! 开头则会执行 do_shell() 命令;如果是 ? 开头则执行 do_help() 命令;如果没有找到该命令,则会执行 default(),如果命令为空则执行 emptyline()。
  • 在执行命令前一般会调用 precmd(),执行后会调用 postcmd(),没有特别需要一般不会调用/重载这两个命令。命令的解析一般由 onecmd() 解析,会找到 do_* 这种方法并调用。
  • 一个特定的命令可以写 do_* 实现,可以写 help_* 作为帮助,也可以直接用前者的 docstring 作为帮助;
  • 为了使用补全功能,可以实现 completedefault() 方法,或者为每个命令创建一个 complete_* 方法,返回供补全的 list;

No comments:

Post a Comment