Redirecting input and output with subprocess
For even more control over the streams of spawned programs, we can employ the
subprocess module we introduced in the preceding chapter. As we learned earlier, this
module can emulate os.popen functionality, but it can also achieve feats such as
bidirectional stream communication (accessing both a program’s input and output)
and tying the output of one program to the input of another.
For instance, this module provides multiple ways to spawn a program and get both its
standard output text and exit status. Here are three common ways to leverage this
module to start a program and redirect its output stream (recall from Chapter 2 that
you may need to pass a shell=True argument to Popen and call to make this section’s
examples work on Unix-like platforms as they are coded here):
C:\...\PP4E\System\Streams> python
>>> from subprocess import Popen, PIPE, call
>>> X = call('python hello-out.py') # convenience
Hello shell world
>>> X
0
>>> pipe = Popen('python hello-out.py', stdout=PIPE)
>>> pipe.communicate()[0] # (stdout, stderr)
b'Hello shell world\r\n'
>>> pipe.returncode # exit status
0
>>> pipe = Popen('python hello-out.py', stdout=PIPE)
>>> pipe.stdout.read()
b'Hello shell world\r\n'
>>> pipe.wait() # exit status
0
The call in the first of these three techniques is just a convenience function (there are
more of these which you can look up in the Python library manual), and the
communicate in the second is roughly a convenience for the third (it sends data to stdin,
reads data from stdout until end-of-file, and waits for the process to end):
Redirecting and connecting to the spawned program’s input stream is just as simple,
though a bit more complex than the os.popen approach with 'w' file mode shown in
the preceding section (as mentioned in the last chapter, os.popen is implemented with
subprocess, and is thus itself just something of a convenience function today):
>>> pipe = Popen('python hello-in.py', stdin=PIPE)
>>> pipe.stdin.write(b'Pokey\n')
6
>>> pipe.stdin.close()
>>> pipe.wait()
0
>>> open('hello-in.txt').read() # output sent to a file
'Hello Pokey\n'
130 | Chapter 3: Script Execution Context