码迷,mamicode.com
首页 > 编程语言 > 详细

multiprocessing 基于进程的“线程式”接口 python

时间:2015-08-27 13:21:21      阅读:241      评论:0      收藏:0      [点我收藏+]

标签:python   多进程   

multiprocessing在python2.6+版本中得到应用。

multi意思为多个,processing意思为进程 也就是实现多进程。可以实现利用调用计算机的多个CPU实现多线程。

multiprocessing是一个包,支持使用类似threading模块的API生成进程。multiprocessing包提供本地和远程两种并发,通过使用子进程而非线程有效地回避了全局解释器锁。 因此,multiprocessing模块允许程序员充分利用一个给定机器的多个处理器。它在Unix和Windows上都可允许。

下面主要介绍进程类

线程是通过创建Process对象,然后调用start()方法来产生的。Process继承了threading.Thread的API。现在举一个multiprocess 的例子:
使用Process创建进程:

from multiprocessing import Process

def f(name):
    print ‘hello‘, name

if __name__ == ‘__main__‘:
    p = Process(target=f, args=(‘bob‘,)) #创建一个线程
    p.start() #调用start方法 启动
    p.join()  

下面是一个活的线程ID的例子:

from multiprocessing import Process
import os

def info(title):
    print title
    print ‘module name:‘, __name__
    if hasattr(os, ‘getppid‘):  # 只在Unix中可使用
        print ‘parent process:‘, os.getppid()
    print ‘process id:‘, os.getpid()

def f(name):
    info(‘function f‘)
    print ‘hello‘, name

if __name__ == ‘__main__‘:
    info(‘main line‘)
    p = Process(target=f, args=(‘bob‘,))
    p.start()
    p.join()

代码中使用os的getpid()获得父进程的ID 使用getip()获得当前进程的ID,另外还可以使用getppid获得父进程的父进程的ID。

IPC(Inter-Process Communication) 进程间的通信

multiprocessing包中有Pipe类和Queue类来分别支持这两种IPC机制。Pipe和Queue可以用来传送常见的对象。
Pipe可以是单向(half-duplex),也可以是双向(duplex)。我们通过mutiprocessing.Pipe(duplex=False)创建单向管道 (默认为双向)。一个进程从PIPE一端输入对象,然后被PIPE另一端的进程接收,单向管道只允许管道一端的进程输入,而双向管道则允许从两端输入。
举例:(单向的)

from multiprocessing import Process, Pipe

def f(conn): #conn为父线程传递过来的pipe对象
    conn.send([42, None, ‘hello‘]) #在pipe对象的一端发送数据
    conn.close() #关闭

if __name__ == ‘__main__‘:
    parent_conn, child_conn = Pipe() #定义两个Pipe对象来创建 
    p = Process(target=f, args=(child_conn,))#创建一个进程 传递的参数为pipe对象
    p.start()
    print parent_conn.recv()   # prints "[42, None, ‘hello‘]" #在父进程中使用另一个pipe对象的recv()方法接受数据
    p.join()

每个连接对象都有send和recv方法,需要注意的是,如果两个进程或者线程同时读取或写入pipe对象的终端,则可能引起终端。如果同时使用pipe的不同终端则不会有风险。

下面举例:(双向)

import multiprocessing as mul
def proc1(pipe):
    pipe.send(‘hello‘)
    print(‘proc1 rec:‘,pipe.recv())
def proc2(pipe):
    print(‘proc2 rec:‘,pipe.recv())
    pipe.send(‘hello, too‘)

if __name__ == ‘__main__‘:
    mul.freeze_support()
    pipe1,pipe2= mul.Pipe() #创建两个pipe对象
    # Pass an end of the pipe to process 1
    p1 = mul.Process(target=proc1, args=(pipe1,)) #创建p1线程
    # Pass the other end of the pipe to process 2
    p2   = mul.Process(target=proc2, args=(pipe2,)) #创建p2线程
    p1.start() #调用线程1
    p2.start()  #调用线程2
    p1.join()  #这里等待线程1执行完成
    p2.join()  #等待线程2执行完成
#输出:
(‘proc2 rec:‘, ‘hello‘)
(‘proc1 rec:‘, ‘hello, too‘)

这个例子实现了两个线程之间的通信,实现了双向通信。线程1: proc1中发送”hello”字符串,线程proc2中接收线程1proc1中发送的”hello”字符串并输出,然后proc2发送”hello, too”字符串,线程1 proc1接收到proc2发送的字符串并输出。

下面介绍另外一种实现IPC的方式:
Queue:
Queue与Pipe相类似,都是先进先出的结构。但Queue允许多个进程放入,多个进程从队列取出对象。Queue使用mutiprocessing.Queue(maxsize)创建,maxsize表示队列中可以存放对象的最大数量。
下面的程序展示了Queue的使用:

from multiprocessing import Process, Queue

def f(q):
    q.put([42, None, ‘hello‘])  #调用主函数中p进程传递过来的进程参数 put函数为向队列中添加一条数据。

if __name__ == ‘__main__‘:
    q = Queue() #创建一个Queue对象
    p = Process(target=f, args=(q,)) #创建一个进程
    p.start()
    print q.get()    # prints "[42, None, ‘hello‘]"
    p.join()

上面是一个queue的简单应用,使用队列q对象调用get函数来取得队列中最先进入的数据。
举一个复杂些的例子:

import multiprocessing
import time
# 向queue中输入数据的函数
def inputQ(queue):
    info = str(os.getpid()) + ‘(put):‘ + str(time.time())
    queue.put(info)

# 向queue中输出数据的函数
def outputQ(queue,lock):
    info = queue.get()
    lock.acquire()
    print (str(os.getpid()) + ‘(get):‘ + info)
    lock.release()

# Main
if __name__ == ‘__main__‘:
    multiprocessing.freeze_support()
    record1 = []   # store input processes
    record2 = []   # store output processes
    lock  = multiprocessing.Lock()    #使用锁方法输出错乱
    queue = multiprocessing.Queue(3)

    # 输入进程
    for i in range(10):
        process = multiprocessing.Process(target=inputQ,args=(queue,))
        process.start()
        record1.append(process)

    # 输出进程
    for i in range(10):
        process = multiprocessing.Process(target=outputQ,args=(queue,lock))
        process.start()
        record2.append(process)

    for p in record1:
        p.join()

    queue.close()  # 如果没有数据进入队列中则关闭队列

    for p in record2:
        p.join()
#输出结果为:
15212(get):7180(put):1440649672.22
8820(get):7020(put):1440649672.85
6164(get):7872(put):1440649673.39
10904(get):9436(put):1440649673.68
5016(get):16840(put):1440649674.07
12004(get):12848(put):1440649674.38
14456(get):11608(put):1440649674.66
2468(get):16884(put):1440649674.85
6464(get):8944(put):1440649674.89
7576(get):15476(put):1440649674.92

这个例子中,创建了二十个进程,十个是用来写入队列数据的,另外十个是用来输出队列中的数据的。

版权声明:本文为博主原创文章,未经博主允许不得转载。

multiprocessing 基于进程的“线程式”接口 python

标签:python   多进程   

原文地址:http://blog.csdn.net/winterto1990/article/details/48025881

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!