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

(yzsuai) #1
scope variables, passed objects and their attributes, and program-wide interpreter
components such as imported modules are shared among all threads in a program;
if one thread assigns a global variable, for instance, its new value will be seen by
other threads. Some care must be taken to control access to shared items, but to
some this seems generally simpler to use than the process communication tools
necessary for forked processes, which we’ll meet later in this chapter and book
(e.g., pipes, streams, signals, sockets, etc.). Like much in programming, this is not
a universally shared view, however, so you’ll have to weigh the difference for your
programs and platforms yourself.

Portability
Perhaps most important is the fact that threads are more portable than forked
processes. At this writing, os.fork is not supported by the standard version of
Python on Windows, but threads are. If you want to run parallel tasks portably in
a Python script today and you are unwilling or unable to install a Unix-like library
such as Cygwin on Windows, threads may be your best bet. Python’s thread tools
automatically account for any platform-specific thread differences, and they pro-
vide a consistent interface across all operating systems. Having said that, the rela-
tively new multiprocessing module described later in this chapter offers another
answer to the process portability issue in some use cases.


So what’s the catch? There are three potential downsides you should be aware of before
you start spinning your threads:


Function calls versus programs
First of all, threads are not a way—at least, not a direct way—to start up another
program. Rather, threads are designed to run a call to a function (technically, any
callable, including bound and unbound methods) in parallel with the rest of the
program. As we saw in the prior section, by contrast, forked processes can either
call a function or start a new program. Naturally, the threaded function can run
scripts with the exec built-in function and can start new programs with tools such
as os.system, os.popen and the subprocess module, especially if doing so is itself a
long-running task. But fundamentally, threads run in-program functions.
In practice, this is usually not a limitation. For many applications, parallel functions
are sufficiently powerful. For instance, if you want to implement nonblocking input
and output and avoid blocking a GUI or its users with long-running tasks, threads
do the job; simply spawn a thread to run a function that performs the potentially
long-running task. The rest of the program will continue independently.


Thread synchronization and queues
Secondly, the fact that threads share objects and names in global process memory
is both good news and bad news—it provides a communication mechanism, but
we have to be careful to synchronize a variety of operations. As we’ll see, even
operations such as printing are a potential conflict since there is only one
sys.stdout per process, which is shared by all threads.


Threads | 187
Free download pdf