Scripts use the preopened stdin and stdout file objects to access those sources, regard-
less of their true nature.
And for readers keeping count, we have just run this single more pager script in four
different ways: by importing and calling its function, by passing a filename command-
line argument, by redirecting stdin to a file, and by piping a command’s output to
stdin. By supporting importable functions, command-line arguments, and standard
streams, Python system tools code can be reused in a wide variety of modes.
Redirecting Streams to Python Objects
All of the previous standard stream redirections work for programs written in any lan-
guage that hook into the standard streams and rely more on the shell’s command-line
processor than on Python itself. Command-line redirection syntax like < filename and
| program is evaluated by the shell, not by Python. A more Pythonesque form of redi-
rection can be done within scripts themselves by resetting sys.stdin and sys.stdout to
file-like objects.
The main trick behind this mode is that anything that looks like a file in terms of
methods will work as a standard stream in Python. The object’s interface (sometimes
called its protocol), and not the object’s specific datatype, is all that matters. That is:
- Any object that provides file-like read methods can be assigned to sys.stdin to
make input come from that object’s read methods. - Any object that defines file-like write methods can be assigned to sys.stdout; all
standard output will be sent to that object’s methods.
Because print and input simply call the write and readline methods of whatever objects
sys.stdout and sys.stdin happen to reference, we can use this technique to both pro-
vide and intercept standard stream text with objects implemented as classes.
If you’ve already studied Python, you probably know that such plug-and-play com-
patibility is usually called polymorphism—it doesn’t matter what an object is, and it
doesn’t matter what its interface does, as long as it provides the expected interface.
This liberal approach to datatypes accounts for much of the conciseness and flexibility
of Python code. Here, it provides a way for scripts to reset their own streams. Exam-
ple 3-9 shows a utility module that demonstrates this concept.
Example 3-9. PP4E\System\Streams\redirect.py
"""
file-like objects that save standard output text in a string and provide
standard input text from a string; redirect runs a passed-in function
with its output and input streams reset to these file-like class objects;
"""
import sys # get built-in modules
class Output: # simulated output file
Standard Streams | 123