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).
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.
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.
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.
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.
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.
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.
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.
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.
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
|