前言
在一般情况下当我们的程序中的某些代码需要并发执行的时候,我们通常会使用多线程(threading),它确实能够解决很多情况下的问题。
但事实上,python中的多线程并不是真正意义上的“并行”,只能算是一段时间内的“并发”。在操作系统的底层,一个多线程的程序共同属于一个进程,程序使用一个cpu在多个线程之间频繁的上下文切换,造成了宏观现象的“并发”,是我们感觉它似乎是‘同时’进行的。
多进程的使用能够实现真正意义的“并行”,每个进程使用一个cpu(如果你的计算机是多核cpu的画话)同时工作。
multiprocessing
python提供了非常好用的多进程包multiprocessing,借助这个包可以轻松实现多进程的想法。提供了Process,Queue等组件。
Process
Process([group [, target [, name [, args [, kwargs]]]]])用于创建进程。target表示调用对象,args表示调用对象的位置参数元组。kwargs表示调用对象的字典。name为别名。group实质上不使用。
下面例子演示是创建函数作为一个子进程并等待其结束:
from multiprocessing import Process
import os
# 子进程要执行的代码
def run_proc(name):
print 'Run child process %s (%s)...' % (name, os.getpid())
if __name__=='__main__':
print 'Parent process %s.' % os.getpid()
p = Process(target=run_proc, args=('test',))
print 'Process will start.'
p.start()
p.join()
print 'Process end.'
执行结果如下:Parent process 928.
Process will start.
Run child process test (929)...
Process end.
join()方法可以等待子进程结束后在继续往下运行,通常用于进程间的同步。复杂的程序不可能只有一个函数,对于包含多个函数的程序我们可以创建类并将类作为一个进程:
import multiprocessing
import time
class ClockProcess(multiprocessing.Process):
def __init__(self, interval):
multiprocessing.Process.__init__(self)
self.interval = interval
def run(self):
n = 5
while n > 0:
print("the time is {0}".format(time.ctime()))
time.sleep(self.interval)
n -= 1
if __name__ == '__main__':
p = ClockProcess(3)
p.start()
执行结果:the time is Tue Apr 21 20:31:30 2015
the time is Tue Apr 21 20:31:33 2015
the time is Tue Apr 21 20:31:36 2015
the time is Tue Apr 21 20:31:39 2015
the time is Tue Apr 21 20:31:42 2015
start()启动某个进程后会自动调用run()方法。Queue(进程共享数据)
在使用多线程时要使线程共享数据只需将该数据声明为全局数据即可,线程是共享内存的,应为他们同属于一个进程。
而在多进程中默认是不共享内存即无法共享数据的。python提供了Queue、Pipes等多种方式来共享数据。
Queue是多进程安全的队列,使用较多,在此以Queue为例。Queue提供了put方法用以插入数据到队列中,提供get方法可以从队列读取并且删除一个元素。
上代码:
import multiprocessing
from multiprocessing import Process
from multiprocessing import Queue
import time
class func(Process):
def __init__(self,queue):
self.queue = queue
super(func, self).__init__()
def run(self):
for i in range(6):
time.sleep(0.5)
self.queue.put(i)
print('put {0} into queue'.format(i))
class fun2(Process):
def __init__(self,queue):
self.queue = queue
super(fun2, self).__init__()
def run(self):
while 1:
if self.queue.qsize()>=2:
for i in range(2):
print('get {0} from queue'.format(self.queue.get()))
if __name__=='__main__':
queue = Queue()
p = func(queue)
g = fun2(queue)
p.start()
g.start()
p.join()
g.terminate()
输出:put 0 into queue
put 1 into queue
get 0 from queue
get 1 from queue
put 2 into queue
put 3 into queue
get 2 from queue
get 3 from queue
put 4 into queue
put 5 into queue
get 4 from queue
get 5 from queue
func向queue中put数据,fun2进程监视queue中的数据,有两个以上的数据时取两个出来。这样就实现了在两个进程之间的数据传输。