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

(yzsuai) #1
C:\...\PP4E\Internet\Sockets> socket-unbuff-server.py
accepting...
receiving...
b'spam\r\n'
receiving...
b'eggs\r\n'
receiving...
b'ham\n'

In other words, even when line buffering is requested, socket wrapper file writes (and
by association, prints) are buffered until the program exits, manual flushes are reques-
ted, or the buffer becomes full.


Solutions


The short story here is this: to avoid delayed outputs or deadlock, scripts that might
send data to waiting programs by printing to wrapped sockets (or for that matter, by
using print or sys.stdout.write in general) should do one of the following:



  • Call sys.stdout.flush periodically to flush their printed output so it becomes
    available as produced, as shown in Example 12-11.

  • Be run with the -u Python command-line flag, if possible, to force the output stream
    to be unbuffered. This works for unmodified programs spawned by pipe tools such
    as os.popen. It will not help with the use case here, though, because we manually
    reset the stream files to buffered text socket wrappers after a process starts. To
    prove this, uncomment Example 12-11’s manual flush calls and the sleep call at its
    end, and run with -u: the first test’s output is still delayed for 5 seconds.

  • Use threads to read from sockets to avoid blocking, especially if the receiving pro-
    gram is a GUI and it cannot depend upon the client to flush. See Chapter 10 for
    pointers. This doesn’t really fix the problem—the spawned reader thread may be
    blocked or deadlocked, too—but at least the GUI remains active during waits.

  • Implement their own custom socket wrapper objects which intercept text write
    calls, encode to binary, and route to a socket with send calls; socket.makefile is
    really just a convenience tool, and we can always code a wrapper of our own for
    more specific roles. For hints, see Chapter 10’s GuiOutput class, the stream redi-
    rection class in Chapter 3, and the classes of the io standard library module (upon
    which Python’s input/output tools are based, and which you can mix in custom
    ways).

  • Skip print altogether and communicate directly with the native interfaces of IPC
    devices, such as socket objects’ raw send and recv methods—these transfer data
    immediately and do not buffer data as file methods can. We can either transfer
    simple byte strings this way or use the pickle module’s dumps and loads tools to
    convert Python objects to and from byte strings for such direct socket transfer
    (more on pickle in Chapter 17).


Making Sockets Look Like Files and Streams | 837
Free download pdf