即日起在codingBlog上分享您的技术经验即可获得积分,积分可兑换现金哦。

python 的多进程编程

编程语言 Ghost_leader 67℃ 0评论
本文目录
[隐藏]

1.multiprocess

         python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程。Python提供了非常好用的多进程包multiprocessing,只需要定义一个函数,Python会完成其他所有事情。借助这个包,可以轻松完成从单进程到并发执行的转换。multiprocessing支持子进程、通信和共享数据、执行不同形式的同步,提供了Process、Queue、Pipe、Lock等组件。




一个最简单的多进程例子。

#!/usr/bin/env python
# -*- coding:utf-8 -*-

from multiprocessing import Pool
from time import sleep

def func(x):
    sleep(1)
    return x*x


if __name__ == '__main__':
    p = Pool(5)
    print p.map(func,[1,2,3,4,5])



这个例子的内容是计算1,2,3,4,5的平方,但是调用了多进程,一共五个进程。每个进程分别取计算平方。




再看另一种多进程的实现方法。

#!/usr/bin/env python

from multiprocessing import Process
import os


def info(title):
    print title
    print 'moudle name:',__name__
    if hasattr(os,'getppid'):
        print 'parent process',os.getppid()
    print 'process id:',os.getpid()

def func(name):
    info('function func')
    print 'hello',name

if __name__ == '__main__':
    info('function main')
    print '------------------'
    p = Process(target=func,args=('Jack',))
    p.start()
    p.join()



看看执行的结果。

function main


moudle name: __main__


parent process 4298


process id: 6323


——————


function func


moudle name: __main__


parent process 6323


process id: 6324


hello Jack



内容是,创建了一个进程去执行了一个function func 函数。可以清楚看到,父子进程之间的关系。




多进程之间的通信

首先进程之间默认是不能共享数据的,而线程是可以的。

#!/usr/bin/env python

from multiprocessing import Process
import threading

def run(info_list,n):
    info_list.append(n)
    print info_list


info = []
print '------- process ----------'
for i in range(10):
    p = Process(target=run,args=[info,i])
    p.start()
    p.join()
print '------- threading --------'
info = []
for i in range(10):
    t = threading.Thread(target=run,args=[info,i])
    t.start()
    t.join()


结果是:

------- process ----------
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
------- threading --------
[0]
[0, 1]
[0, 1, 2]
[0, 1, 2, 3]
[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4, 5]
[0, 1, 2, 3, 4, 5, 6]
[0, 1, 2, 3, 4, 5, 6, 7]
[0, 1, 2, 3, 4, 5, 6, 7, 8]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


由此可见,进程之间是不共享数据的。而线程是可以的。

1.1.


2.进程间通信

2.1.第一,通过Queue来实现信息共享。

将所有进程产生的数据都放进Queue里面。这样的话,x进程可以去使用y进程产生的数据。

#!/usr/bin/python

from multiprocessing import Process,Queue

def func(q,n):
    q.put(['index',n])

if __name__ == '__main__':
    q = Queue()
    for i in range(5):
        p = Process(target=func,args=(q,i))
        p.start()
    while True:
        print q.get()



执行结果是。可以完全的取出0到4.

结果:


[‘index’, 2]


[‘index’, 4]


[‘index’, 0]


[‘index’, 1]


[‘index’, 3]




第二,通过pipe进行多进程间通信。

    pipe对象返回的元组分别代表的是管道的两端,管道默认的是全双工。两端都支持send和recv方法。两个进程分别操作管道两端的时候不会有冲突,两个进程对管道一端同时读写可能会有冲突:

如果定义了 p = Pipe(duplex=False)的单向管道,则p[0]只负责接受消息,p[1]只负责发送消息。

from multiprocessing import Pipe, Process

def func(p):
    p.send([1, 'str', None])
    p.close()

if __name__ == "__main__":
    parent_side, child_side = Pipe()
    p = Process(target=func, args=(child_side,))
    p.start()
    print parent_side.recv()
    p.join()



第三,防止访问冲突。

通过加锁的方式可以对一个资源实现独享。

from multiprocessing import Lock, Process

def lock_func(l, number):
    l.acquire()
    print "Number is: %d" % number
    l.release()

if __name__ == "__main__":
    l = Lock()
    for number in range(10):
        Process(target=lock_func, args=(l, number,)).start()





3.线程池的编程。

一开始的时候就使用线程池,操作十分简便。

from multiprocessing import Pool
import time

def f(x):
    print x*x
    time.sleep(1)
    return x*x

pool = Pool(processes=4)
res_list = []

for i in range(10):
    res = pool.apply_async(f,[i,])
    res.get(timeout=2)



使用apply_async的非阻塞型。而apply是非阻塞型。get()方法可以取得返回值。不然的话返回的是一个进程池的对象。









转载请注明:CodingBlog » python 的多进程编程

喜欢 (0)or分享 (0)
发表我的评论
取消评论

*

表情