[Python编程(第4版)].(Programming.Python.4th.Edition).Mark.Lutz.文字版

(yzsuai) #1

Output stream buffering: A first look


Notice that the last test in the preceding code didn’t attempt to read the command’s
output pipe. If we do, we may have to run the target script in unbuffered mode with the
-u Python command-line flag or change the script to flush its output manually with
sys.stdout.flush. Otherwise, the text printed to the standard output stream might not
be flushed from its buffer when os._exit is called in this case for immediate shutdown.
By default, standard output is fully buffered when connected to a pipe like this; it’s only
line-buffered when connected to a terminal:


>>> pipe = os.popen('python testexit_os.py')
>>> pipe.read() # streams not flushed on exit
''

>>> pipe = os.popen('python -u testexit_os.py') # force unbuffered streams
>>> pipe.read()
'Bye os world\n'

Confusingly, you can pass mode and buffering argument to specify line buffering in
both os.popen and subprocess.Popen, but this won’t help here—arguments passed to
these tools pertain to the calling process’s input end of the pipe, not to the spawned
program’s output stream:


>>> pipe = os.popen('python testexit_os.py', 'r', 1) # line buffered only
>>> pipe.read() # but my pipe, not program's!
''

>>> from subprocess import Popen, PIPE
>>> pipe = Popen('python testexit_os.py', bufsize=1, stdout=PIPE) # for my pipe
>>> pipe.stdout.read() # doesn't help
b''

Really, buffering mode arguments in these tools pertain to output the caller writes to
a command’s standard input stream, not to output read from that command.


If required, the spawned script itself can also manually flush its output buffers period-
ically or before forced exits. More on buffering when we discuss the potential for
deadlocks later in this chapter, and again in Chapters 10 and 12 where we’ll see how it
applies to sockets. Since we brought up subprocess, though, let’s turn to its exit tools
next.


Exit status with subprocess


The alternative subprocess module offers exit status in a variety of ways, as we saw in
Chapters 2 and 3 (a None value in returncode indicates that the spawned program has
not yet terminated):


C:\...\PP4E\System\Exits> python
>>> from subprocess import Popen, PIPE, call
>>> pipe = Popen('python testexit_sys.py', stdout=PIPE)
>>> pipe.stdout.read()
b'Bye sys world\r\n'

218 | Chapter 5: Parallel System Tools

Free download pdf