Previous Page
Next Page

10.11. 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 verb's action.

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

self.do_verb('and the rest')

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

10.11.1. Initializing a Cmd Instance

Your subclass of cmd.Cmd, if it defines its own _ _init_ _ special method, must call the base class's _ _init_ _, whose signature is as follows.

_ _init_ _

Cmd._ _init_ _(self, completekey='Tab', stdin=sys.stdin, stdout=sys.stdout)

Initializes instance self with specified or default values for completekey (name of the key to use for command completion with the readline module; pass None to disable command completion), stdin (file object to get input from), and stdout (file object to emit output to).

If your subclass does not define _ _init_ _, then it inherits the one from base class cmd.Cmd. In this case, to instantiate your subclass, call it, with optional parameters completekey, stdin, and stdout, as documented in the previous paragraph.


10.11.2. 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 interactive session of line-oriented commands. cmdloop starts by calling c.preloop( ), then emits 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. Whatever the value of flag, cmdloop calls flag=c.postcmd(flag, s) to check if the loop should terminate. If flag is now true, the loop terminates; otherwise, the loop repeats again. When the loop terminates, cmdloop calls c.postloop( ), then terminates. This structure of cmdloop that I just described is easiest to understand by looking at equivalent Python code:

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

cmdloop is a good example of the classic 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 some or all of 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 method Cmd.default 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 nonempty 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 reexecutes the last nonblank 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 to process as a command. Normally, subclasses do not override onecmd. Cmd.onecmd sets c.lastcmd=s. Then onecmd calls do_verb when s starts with the word verb and the subclass supplies such a method; otherwise, it calls emptyline or default, as explained earlier. In any case, Cmd.onecmd returns the result of whatever other method it calls 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 tentative 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 does nothing.

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 method Cmd.preloop does nothing.


10.11.3. Attributes of Cmd Instances

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


identchars

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


intro

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


lastcmd

The last nonblank 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 I do not cover here, let you exert fine-grained control on many formatting details of help messages.

10.11.4. 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 True
    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\chapter10\CmdEx.py
(Cmd) help
Documented commands (type help <topic>):
= == == == == == == == == == == == == == == == == == == == =
print           stop Undocumented commands:
= == == == == == == == == == == =
help
(Cmd) help print
print (any string): outputs (any string)
(Cmd) print hi there
hi there
(Cmd) stop


Previous Page
Next Page