简介

Python多进程主要集中在multiprocessing模块中实现相关功能。如

  • 进程的创建(Process)
  • Pool的使用(Pool)
  • 多个进程之间的数据交换(Queue, Pipes)
  • 多个进程之间数据共享(Value, Array, Manager)
  • 多个进程之间的同步操作(Lock)

实现样例

在Windows系统实现多进程样例时,

if __name__ == "__main__":

是必要的,确保主模块可以由新的Python解释器安全导入,而不会引起意外的副作用。

Process

使用multiprocessing.Process可以创建一个新的进程,通过start()方法启动进程。

最佳实践是在start()之后执行join()方法,因为在Unix系统当一个进程结束但是没有join,该进程会变成僵尸进程(a zombie)。

但是join()方法在进程使用Queue时则不需要添加,反而可能会因为join方法的添加顺序问题导致死锁。因为一个进程put数据到Queue中会等待数据被消费才会终止,如果存在数据未被消费则进程一直等待。

# Process 构造参数说明
class multiprocessing.Process(group=None, target=None, name=None, args=(), kwargs={})
    @param group
    @param target: run()方法可调用的对象
    @param name: 进程名称
    @param args: 目标调用对象的参数, 默认无参数调用
    @param kwargs: 目标调用的关键字参数字典
# -*- coding:utf-8 -*-
# @author Marvin Yang
# Process示例

from multiprocessing import Process

def multi(x, y):
    print "%s multi %s = %s" % (x, y, x*y)
    return x * y

def process_demo():
    p = Process(target=multi, args=(3, 4))
    p.start()
    p.join()
    
def multi_process_demo():
    for x in range(0, 5):
        for y in range(1, 4):
            p = Process(target=multi, args=(x, y))
            p.start()
            p.join()
    
if __name__ == "__main__":
    # 单个进程
    process_demo()
    
    # 多个进程
    multi_process_demo()

Pool

进程池可创建多个进程供使用,且提供了多个不同的执行方法。如apply, apply_async, map, map_async等。

# -*- coding:utf-8 -*-
# @author Marvin Yang
# Pool实现样例

from multiprocessing import Process, Pool, Queue

def x2(x):
    return x*x
    
def multi(x, y):
    print "%s multi %s = %s" % (x, y, x*y)
    return x * y
    
def pool_demo():
    """ map同内置函数map()类似,
    将目标调用对象作用于每一个可迭代参数上
    意味着如果目标调用对象包含多个参数则不适合用map方法
    """
    pool = Pool(processes=4)
    print(pool.map(x2, [random.randrange(0, 10), 45, 3, 4, 6]))

def pool_apply_demo():
    """ apply同内置apply()类似,
    可以有返回值
    一个apply使用Pool中的一个进程
    """
    pool = Pool(processes=4)
    r = pool.apply_async(x2, args=(3, ))
    s = pool.apply_async(multi, args=(4, 5))
    print(r.get())
    print(s.get())
    
if __name__ == "__main__":
    # pool demo
    pool_demo()
    pool_apply_demo()

Queue

通过Queue实现多个进程之间的数据交换。Pipes同样也可以实现多个进程之间的数据交换,一个头用来输入,一个头用来接收。

# -*- coding:utf-8 -*-
# @author Marvin Yang

from multiprocessing import Process, Pool, Queue
import time

def queue_put_demo(queue):
    """ 推送数据到Queue
    
    """
    for i in range(0, 10):
        print "input queue: %s" % i
        queue.put(["here is a queue demo", "queue", "%s" % i])
        #time.sleep(1)


def queue_get_demo(queue):
    """ 从Queue中获取数据展示
    
    """
    count = 0
    while count < 10 or not queue.empty():
        if queue.empty():
            time.sleep(2)
        else:
            obj = queue.get()
            for item in obj:
                print item, len(item)
        count += 1


def queue_demo():
    """ 两个进程,一个推送数据到队列,一个从队列中获取数据展示
    
    """
    queue = Queue()
    put_p = Process(target=queue_put_demo, args=(queue, ))
    get_p = Process(target=queue_get_demo, args=(queue, ))
    put_p.start()
    get_p.start()


if __name__ == "__main__":
    queue_demo()

more

通过上述介绍简单的多进程操作可以满足日常的一些数据处理功能,更多的多进程的细节和功能还需要继续学习。

参考文献

python-2.7.14-docs-html -> module: multiprocessing