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

(yzsuai) #1

specific process-based roles; servers provide data sources which are longer-lived and
more loosely coupled (though a GUI can also display data from independent servers).
Whatever we call it, this model both avoids blocking the GUI while tasks run and avoids
potentially parallel updates to the GUI itself.


As a more concrete example, suppose your GUI needs to display telemetry data sent in
real time from a satellite over sockets (an IPC tool introduced in Chapter 5). Your
program has to be responsive enough to not lose incoming data, but it also cannot get
stuck waiting for or processing that data. To achieve both goals, spawn threads that
fetch the incoming data and throw it on a queue, to be picked up and displayed peri-
odically by the main GUI thread. With such a separation of labor, the GUI isn’t blocked
by the satellite, nor vice versa—the GUI itself will run independently of the data
streams, but because the data stream threads can run at full speed, they’ll be able to
pick up incoming data as fast as it’s sent. GUI event loops are not generally responsive
enough to handle real-time inputs. Without the data stream threads, we might lose
incoming telemetry; with them, we’ll receive data as it is sent and display it as soon as
the GUI’s event loop gets around to picking it up off the queue—plenty fast for the real
human user to see. If no data is sent, only the spawned threads wait, not the GUI itself.


In other scenarios, threads are required just so that the GUI remains active during long-
running tasks. While downloading a reply from a web server, for example, your GUI
must be able to redraw itself if covered or resized. Because of that, the download call
cannot be a simple function call; it must run in parallel with the rest of your program—
typically, as a thread. When the result is fetched, the thread must notify the GUI that
data is ready to be displayed; by placing the result on a queue, the notification is
simple—the main GUI thread will find it the next time it checks the queue in its timer
callback function. For example, we’ll use threads and queues this way in the PyMailGUI
program in Chapter 14, to allow multiple overlapping mail transfers to occur without
blocking the GUI itself.


Placing Data on Queues


Whether your GUIs interface with satellites, websites, or something else, this thread-
based model turns out to be fairly simple in terms of code. Example 10-18 is the GUI
equivalent of the queue-based threaded program we met earlier in Chapter 5 (compare
this with Example 5-14). In the context of a GUI, the consumer thread becomes the
GUI itself, and producer threads add data to be displayed to the shared queue as it is
produced. The main GUI thread uses the tkinter after method to check the queue for
results instead of an explicit loop.


Example 10-18. PP4E\Gui\Tools\queuetest-gui.py


GUI that displays data produced and queued by worker threads


import _thread, queue, time
dataQueue = queue.Queue() # infinite size


636 | Chapter 10: GUI Coding Techniques

Free download pdf