Enter a number>6 squared is 36
Enter a number>Bye
This is an artificial example, of course, but the techniques illustrated are widely appli-
cable. For instance, it’s straightforward to add a GUI interface to a program written to
interact with a command-line user. Simply intercept standard output with an object
such as the Output class instance shown earlier and throw the text string up in a window.
Similarly, standard input can be reset to an object that fetches text from a graphical
interface (e.g., a popped-up dialog box). Because classes are plug-and-play compatible
with real files, we can use them in any tool that expects a file. Watch for a GUI stream-
redirection module named guiStreams in Chapter 10 that provides a concrete imple-
mentation of some of these ideas.
The io.StringIO and io.BytesIO Utility Classes
The prior section’s technique of redirecting streams to objects proved so handy that
now a standard library module automates the task for many use cases (though some
use cases, such as GUIs, may still require more custom code). The standard library tool
provides an object that maps a file object interface to and from in-memory strings. For
example:
>>> from io import StringIO
>>> buff = StringIO() # save written text to a string
>>> buff.write('spam\n')
5
>>> buff.write('eggs\n')
5
>>> buff.getvalue()
'spam\neggs\n'
>>> buff = StringIO('ham\nspam\n') # provide input from a string
>>> buff.readline()
'ham\n'
>>> buff.readline()
'spam\n'
>>> buff.readline()
''
As in the prior section, instances of StringIO objects can be assigned to sys.stdin and
sys.stdout to redirect streams for input and print calls and can be passed to any code
that was written to expect a real file object. Again, in Python, the object interface, not
the concrete datatype, is the name of the game:
>>> from io import StringIO
>>> import sys
>>> buff = StringIO()
>>> temp = sys.stdout
>>> sys.stdout = buff
>>> print(42, 'spam', 3.141) # or print(..., file=buff)
126 | Chapter 3: Script Execution Context