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

(yzsuai) #1
not written in Python, for which neither manual flush calls nor -u are an option.
See “More on Stream Buffering: pty and Pexpect” on page 233.

Thread can avoid blocking a main GUI, too, but really just delegate the problem (the
spawned thread will still be deadlocked). Of the options listed, the first two—manual
flushes and command-line arguments—are often the simplest solutions. In fact, be-
cause it is so useful, the second technique listed above merits a few more words. Try
this: comment-out all the sys.stdout.flush calls in Examples 5-22 and 5-23 (the files
pipes.py and pipes-testchild.py) and change the parent’s spawn call in pipes.py to this
(i.e., add a -u command-line argument):


spawn('python', '-u', 'pipes-testchild.py', 'spam')

Then start the program with a command line like this: python -u pipes.py. It will work
as it did with the manual stdout flush calls, because stdout will be operating in unbuf-
fered mode in both parent and child.


We’ll revisit the effects of unbuffered output streams in Chapter 10, where we’ll code
a simple GUI that displays the output of a non-GUI program by reading it over both a
nonblocking socket and a pipe in a thread. We’ll explore the topic again in more depth
in Chapter 12, where we will redirect standard streams to sockets in more general ways.
Deadlock in general, though, is a bigger problem than we have space to address fully
here. On the other hand, if you know enough that you want to do IPC in Python, you’re
probably already a veteran of the deadlock wars.


Anonymous pipes allow related tasks to communicate but are not directly suited for
independently launched programs. To allow the latter group to converse, we need to
move on to the next section and explore devices that have broader visibility.


More on Stream Buffering: pty and Pexpect
On Unix-like platforms, you may also be able to use the Python pty standard library
module to force another program’s standard output to be unbuffered, especially if it’s
not a Python program and you cannot change its code.
Technically, default buffering for stdout in other programs is determined outside Py-
thon by whether the underlying file descriptor refers to a terminal. This occurs in the
stdio file system library and cannot be controlled by the spawning program. In general,
output to terminals is line buffered, and output to nonterminals (including files, pipes,
and sockets) is fully buffered. This policy is used for efficiency. Files and streams created
within a Python script follow the same defaults, but you can specify buffering policies
in Python’s file creation tools.
The pty module essentially fools the spawned program into thinking it is connected to
a terminal so that only one line is buffered for stdout. The net effect is that each newline
flushes the prior line—typical of interactive programs, and what you need if you wish
to grab each piece of the printed output as it is produced.
Note, however, that the pty module is not required for this role when spawning Python
scripts with pipes: simply use the -u Python command-line flag, pass line-buffered mode

Interprocess Communication | 233
Free download pdf