10.10. Richer-Text I/O
The tools we have covered so far support the minimal subset of text I/O functionality that all platforms supply. Most platforms also offer richer-text I/O capabilities, such as responding to single keypresses (not just entire lines of text) and showing text in any spot on the terminal (not just sequentially).
Python extensions and core Python modules let you access platform-specific functionality. Unfortunately, various platforms expose this functionality in different ways. To develop cross-platform Python programs with rich-text I/O functionality, you may need to wrap different modules uniformly, importing platform-specific modules conditionally (usually with the try/except idiom covered in try/except on page 122).
10.10.1. The readline Module
The readline module wraps the GNU
Readline Library. GNU Readline lets the user edit text lines during interactive input, and recall previous lines for editing and reentry. Readline is installed on many Unix-like platforms, and it's available at http://cnswww.cns.cwru.edu/~chet/readline/rltop.html. A Windows port (http://starship.python.net/crew/kernr/) is available, but is not widely deployed. Chris Gonnerman's module, Alternative Readline for Windows, implements a subset of Python's standard readline module (using a small dedicated .pyd file instead of Readline) and is found at http://newcenturycomputers.net/projects/readline.html. One way to use Readline on Windows is to install Gary Bishop's version of readline (http://sourceforge.net/projects/uncpythontools); this version does, however, require two other Python add-ons (ctypes and PyWin32), and so is not quite trivial to install.
When readline is available, Python uses it for all line-oriented input, such as raw_input. The interactive Python interpreter always tries to load readline to enable line editing and recall for interactive sessions. Some readline functions control advanced functionality, particularly history, for recalling lines entered in previous sessions, and completion, for context-sensitive completion of the word being entered. (See http://cnswww.cns.cwru.edu/~chet/readline/rltop.html#Documentation for GNU Readline documentation, with details on configuration commands.) Alternative Readline also supports history, but the completion-related functions it supplies are dummy: these functions, in Alternative Readline, don't perform any operation and exist only for compatibility with GNU Readline.
Adds string s as a line at the end of the history buffer.
Clears the history buffer.
Returns the current completer function (as last set by set_completer), or None if no completer function is set.
Returns the number of lines of history that are saved to the history file. When the returned value is less than 0, all lines in the history are saved.
Gives Readline a configuration command. To let the user hit Tab to request completion, call parse_and_bind('tab: complete'). See the Readline documentation for other useful values of string readline_cmd.
A useful completion function is in module rlcompleter. In an interactive interpreter session (or, more practically, in the startup file that the interpreter runs at the start of each interactive session, as covered in "Environment Variables" on page 22), enter:
import readline, rlcompleter readline.parse_and_bind('tab: complete')
For the rest of this interactive session, you can hit Tab during line editing and get completion for global names and object attributes.
Loads history lines from the text file whose name or path is filename.
Makes Readline load a text file, where each line is a configuration command. When filename is None, Readline loads the same file as last time.
Sets the completion function. When f is None, Readline disables completion. Otherwise, when the user types a partial word start, then Tab, Readline calls f(start, i), with i initially 0. f returns the ith possible word starting with start, or None when there are no more. Readline loops calling f, with i set to 0, 1, 2, etc., until f returns None.
Sets the number of lines of history that are saved to the history file. When x is less than 0, all lines in the history are saved.
Saves history lines to the text file whose name or path is filename.
10.10.2. Console I/O
"Terminals" today are usually text windows on a graphical screen. You may also use a true terminal or the console
(main screen) of a personal computer in text mode. All kinds of terminals in use today offer advanced text I/O functionality, but you access this functionality in platform-dependent ways. The curses package works only on Unix-like platforms (there are persistent rumors of Windows ports of it, but I've never found a working one). Modules msvcrt, WConio, and Console work only on Windows.
10.10.2.1. The curses package
The traditional Unix approach to advanced terminal I/O is named curses, for obscure historical reasons. The Python package curses affords reasonably simple use, but still lets you exert detailed control if required. I cover a small subset of curses, just enough to let you write programs with rich-text I/O functionality. (See Eric Raymond's tutorial "Curses Programming with Python," available at http://py-howto.sourceforge.net/curses/curses.html, for more information.) Whenever I mention the screen in this section, I mean the screen of the terminal (for example, the text window of a terminal-emulator program).
The simplest and most effective way to use curses is through the curses.wrapper module, which supplies a single function.
Performs curses initialization, calls func(stdscr, *args), performs curses finalization (setting the terminal back to normal behavior), and finally returns func's result. The first argument that wrapper passes to func is stdscr, an object of type curses.Window representing the whole terminal screen. wrapper sets the terminal back to normal behavior, whether func terminates normally or propagates an exception.
func should be a function that performs all the tasks in your program that may need curses functionality. In other words, func normally contains (or more commonly calls, directly or indirectly, functions containing) all of your program's functionality, save perhaps for some noninteractive initialization and/or finalization tasks.
curses models text and background colors of characters as character attributes. Colors available on the terminal are numbered from 0 to curses.COLORS. Function color_content takes a color number n as its argument and returns a tuple (r, g, b) of integers between 0 and 1000 giving the amount of each primary color in n. Function color_pair takes a color number n as its argument and returns an attribute code that you can pass to various methods of a curses.Window object in order to display text in that color.
curses lets you create multiple instances of type curses.Window, each corresponding to a rectangle on the screen. You can also create exotic variants, such as instances of Panel, polymorphic with Window but not tied to a fixed screen rectangle. You do not need such advanced functionality in simple curses programs: just use the Window object stdscr that curses.wrapper gives you. Call w.refresh( ) to ensure that changes made to any Window instance w, including stdscr, show up on screen. curses can buffer the changes until you call refresh. An instance w of Window supplies, among many others, the following frequently used methods.
w.addstr([y, x, ]s[, attr])
Puts the characters in string s, with attribute attr, on w at the given coordinates (x, y), overwriting any previous contents. All curses functions and methods accept coordinate arguments in reverse order, with y (the row number) before x (the column number). If you omit y and x, addstr uses w's current cursor coordinates. If you omit attr, addstr uses w's current default attribute. In any case, addstr, when done adding the string, sets w's current cursor coordinates to the end of the string it has added.
w.clrtobot( ) w.clrtoeol( )
clrtoeol writes blanks from w's current cursor coordinates to the end of the line. clrtobot, in addition, also blanks all lines lower down on the screen.
Deletes one character from w at coordinates (x, y). If you omit the y and x arguments, delch uses w's current cursor coordinates. In any case, delch does not change w's current cursor coordinates. All the following characters in line y, if any, shift left by one.
Deletes from w the entire line at w's current cursor coordinates, and scrolls up by one line all lines lower down on the screen.
Writes spaces to the entire terminal screen.
Returns an integer c corresponding to a user keystroke. A value between 0 and 255 represents an ordinary character, while a value greater than 255 represents a special key. curses supplies names for special keys, so you can test c for equality with readable constants such as curses.KEY_HOME (the Home special key), curses.KEY_LEFT (the left-arrow special key), and so on. (The list of all curses special-key names (about 100 of them) is in Python's free documentation, specifically in the Python Library Reference, in the subsection named "Constants" of the section named "curses.") If you have set window w to no-delay mode by calling w.nodelay(True), w.getch raises an exception if no keystroke is ready. By default, w.getch waits until the user hits a key.
Returns w's current cursor coordinates as a tuple (y, x).
w.insstr([y, x, ]s[, attr])
Inserts the characters in string s, with attribute attr, on w at coordinates (x, y), shifting the rest of line rightward. Any characters shifted beyond line end are lost. If you omit y and x, insstr uses w's current cursor coordinates. If you omit attr, insstr uses w's current default attribute. In any case, when done inserting the string, insstr sets w's current cursor coordinates to the first character of the string it has inserted.
Moves w's cursor to the given coordinates (x, y).
Sets w to no-delay mode when flag is true; resets w back to normal mode when flag is false. No-delay mode affects method w.getch.
Updates window w on screen with all changes the program has effected on w.
The curses.textpad module supplies the Textpad class, which lets you support advanced input and text editing.
Creates and returns an instance t of class Textpad that wraps the curses window instance window. Instance t has one frequently used method:
Lets the user perform interactive editing on the contents of the window instance that t wraps. The editing session supports simple Emacs-like key bindings: normal characters overwrite the window's previous contents, arrow keys move the cursor, and Ctrl-H deletes the character to the cursor's left. When the user hits Ctrl-G, the editing session ends, and edit returns the window's contents as a single string, with newlines as line separators.
10.10.2.2. The msvcrt Module
The msvcrt module, available only on Windows, supplies functions that let Python programs access a few proprietary extras supplied by the Microsoft Visual C++'s runtime library msvcrt.dll. Some msvcrt functions let you read user input character by character rather than reading a full line at a time.
getch( ) getche( )
Reads and returns one character from keyboard input, and waits if no character is yet available for reading. getche also echoes the character to screen (if printable), while getch doesn't. When the user presses a special key (arrows, function keys, etc.), it's seen as two characters: first a chr(0) or chr(224), then a second character that, together with the first one, defines the special key the user pressed. To find out what getch returns for any key, run the following small script on a Windows machine:
import msvcrt print "press z to exit, or any other key to see the key's code:"
c = msvcrt.getch( )
if c == 'z': break
print "%d (%r)" % (c, c)
Returns true when a character is available for reading (getch, if called, would return immediately); otherwise, False (getch, if called, would wait).
"Ungets" character c; the next call to getch or getche returns c. It's an error to call ungetch twice without intervening calls to getch or getche.
10.10.2.3. The WConio and Console modules
Two Windows-specific extension modules supply single-character keyboard input (like msvcrt) and the ability to emit characters to specified positions on the screen. Chris Gonnerman's Windows Console I/O module is small, simple, and easy to use; you can freely download it from http://newcenturycomputers.net/projects/wconio.html. Fredrik Lundh's Console module
is very complete and functionally rich; you can freely download it from http://www.effbot.org/efflib/console/.