[ Team LiB ] Previous Section Next Section

10.9 Interactive Command Sessions

The cmd module offers a simple way to handle interactive sessions of commands. Each command is a line of text. The first word of each command is a verb defining the requested action. The rest of the line is passed as an argument to the method that implements the action that the verb requests.

Module cmd supplies class Cmd to use as a base class, and you define your own subclass of cmd.Cmd. The subclass supplies methods with names starting with do_ and help_, and may also optionally override some of Cmd's methods. When the user enters a command line such as verb and the rest, as long as the subclass defines a method named do_verb, Cmd.onecmd calls:

self.do_verb('and the rest')

Similarly, as long as the subclass defines a method named help_verb, Cmd.do_help calls it when the command line starts with either 'help verb' or '?verb'. Cmd, by default, also shows suitable error messages if the user tries to use, or asks for help about, a verb for which the subclass does not define a needed method.

10.9.1 Methods of Cmd Instances

An instance c of a subclass of class Cmd supplies the following methods (many of these methods are meant to be overridden by the subclass).

cmdloop

c.cmdloop(intro=None)

Performs an entire interactive session of line-oriented commands. cmdloop starts by calling c.preloop( ), then outputs string intro (c.intro, if intro is None). Then c.cmdloop enters a loop. In each iteration of the loop, cmdloop reads line s with s=raw_input(c.prompt). When standard input reaches end-of-file, cmdloop sets s='EOF'. If s is not 'EOF', cmdloop preprocesses string s with s=c.precmd(s), then calls flag=c.onecmd(s). When onecmd returns a true value, this is a tentative request to terminate the command loop. Now cmdloop calls flag=c.postcmd(flag,s) to check if the loop should terminate. If flag is now true, the loop terminates; otherwise another iteration of the loop executes. If the loop is to terminate, cmdloop calls c.postloop( ), then terminates. This structure of cmdloop is probably easiest to understand by showing Python code equivalent to the method just described:

def cmdloop(self, intro=None):
    self.preloop(  )
    if intro is None: intro = self.intro
    print intro
    while True:
        try: s = raw_input(self.prompt)
        except EOFError: s = `EOF'
        else: s = self.precmd(s)
        flag = self.onecmd(s)
        flag = self.postcmd(flag, s)
        if flag: break
    self.postloop(  )

cmdloop is a good example of the design pattern known as Template Method. Such a method performs little substantial work itself; rather, it structures and organizes calls to other methods. Subclasses may override the other methods, to define the details of class behavior within the overall framework thus established. When you inherit from Cmd, you almost never override method cmdloop, since cmdloop's structure is the main thing you get by subclassing Cmd.

default

c.default(s)

c .onecmd calls c.default(s) when there is no method c.do_verb for the first word verb of line s. Subclasses often override default. The base class Cmd.default method prints an error message.

do_help

c.do_help(verb)

c .onecmd calls c.do_help(verb) when command line s starts with 'help verb' or '?verb'. Subclasses rarely override do_help. The Cmd.do_help method calls method help_verb if the subclass supplies it, otherwise it displays the docstring of method do_verb if the subclass supplies that method with a non-empty docstring. If the subclass does not supply either source of help, Cmd.do_help outputs a message to inform the user that no help is available on verb.

emptyline

c.emptyline(  )

c .onecmd calls c.emptyline( ) when command line s is empty or blank. Unless a subclass overrides this method, the base-class method Cmd.emptyline is called and re-executes the last non-blank command line seen, stored in the attribute c.lastcmd of c.

onecmd

c.onecmd(s)

c .cmdloop calls c.onecmd(s) for each command line s that the user inputs. You can also call onecmd directly, if you have independently obtained a line s that you need to process as a command. Normally, subclasses do not override method onecmd. Cmd.onecmd unconditionally sets c.lastcmd=s. Then, onecmd calls do_verb if s starts with the word verb and if the subclass supplies such a method, or else methods emptyline or default, as explained earlier. In any case, Cmd.onecmd returns the result of whatever other method it ends up calling, to be interpreted by postcmd as a termination-request flag.

postcmd

c.postcmd(flag,s)

c .cmdloop calls c.postcmd(flag,s) for each command line s, after c.onecmd(s) has returned value flag. If flag is true, the command just executed is posing a conditional request to terminate the command loop. If postcmd returns a true value, cmdloop's loop terminates. Unless your subclass overrides this method, the base-class method Cmd.postcmd is called, and returns flag itself as the method's result.

postloop

c.postloop(  )

c .cmdloop calls c.postloop( ) when cmdloop's loop terminates. Unless your subclass overrides this method, the base-class method Cmd.postloop is called, and does nothing at all.

precmd

c.precmd(s)

c .cmdloop calls s=c.precmd(s) to preprocess each command line s. The current leg of the loop bases all further processing on the string that precmd returns. Unless your subclass overrides this method, the base-class method Cmd.precmd is called, and returns s itself as the method's result.

preloop

c.preloop(  )

c .cmdloop calls c.preloop( ) before cmdloop's loop begins. Unless your subclass overrides this method, the base class Cmd.preloop method is called, and does nothing at all.

10.9.2 Attributes of Cmd Instances

An instance c of a subclass of class Cmd supplies the following attributes:

identchars

A string that contains all characters that can be part of a verb; by default, c.identchars contains letters, digits, and underscore (_)

intro

The message that cmdloop outputs first, when called with no argument

lastcmd

The last non-blank command line seen by onecmd

prompt

The string that cmdloop uses to prompt the user for interactive input. You almost always bind c.prompt explicitly, or override prompt as a class attribute of your subclass, because the default Cmd.prompt is just '(Cmd) '.

use_rawinput

When false (default is true), cmdloop prompts and inputs via calls to methods of sys.stdout and sys.stdin, rather than via raw_input

Other attributes of Cmd instances, which are not covered here, let you exert fine-grained control on many formatting details of help messages.

10.9.3 A Cmd Example

The following example shows how to use cmd.Cmd to supply the verbs print (to output the rest of the line) and stop (to end the loop):

import cmd

class X(cmd.Cmd):
    def do_print(self, rest): print rest
    def help_print(self): print "print (any string): outputs (any string)"
    def do_stop(self, rest): return 1
    def help_stop(self): print "stop: terminates the command loop"

if _ _name_ _=  ='_ _main_ _': X(  ).cmdloop(  )

A session using this example might proceed as follows:

C:\>\python22\python \examples\chapter19\CmdEx.py
(Cmd) help
Documented commands (type help <topic>):
=  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  =
print           stop
Undocumented commands:
=  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==  =
help
(Cmd) help print
print (whatever): outputs string (whatever)
(Cmd) print hi there
hi there
(Cmd) stop
    [ Team LiB ] Previous Section Next Section