程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长

+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

从零开始的Python学习Episode 23——进程

发布于2019-08-08 16:08     阅读(677)     评论(0)     点赞(5)     收藏(0)


---恢复内容开始---

进程

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

  multiprocessing包是Python中的多进程管理包。与threading.Thread类似,它可以利用multiprocessing.Process对象来创建一个进程。该进程可以运行在Python程序内部编写的函数。该Process对象与Thread对象的用法相同,也有start(), run(), join()的方法。此外multiprocessing包中也有Lock/Event/Semaphore/Condition类 (这些对象可以像多线程那样,通过参数传递给各个进程),用以同步进程,其用法与threading包中的同名类一致。所以,multiprocessing的很大一部份与threading使用同一套API,只不过换到了多进程的情境。

 

创建进程的两种方法

调用内置的方法

复制代码
from multiprocessing import Process
import time

def fun(name):
    print(name+' is running')
    time.sleep(2)
    print(name+' end')

if __name__ == '__main__':
    pro = Process(target=fun,args=('no1',))
    pro.start()
复制代码

自定义类

复制代码
from multiprocessing import Process
import os

class Myprocess(Process):
    def __init__(self,name):
        Process.__init__(self)
        self.name = name
    def run(self):
        print(os.getpid())
        print(self.name+' is running')
if __name__=='__main__':
    p1 = Myprocess('1')
    p2=Myprocess('2')
    p3=Myprocess('3')

    p1.start()
    p2.start()
    p3.start()
复制代码

注意:在运行的时候要在main里面运行,因为子进程是通过导入模块的方式拿到父进程的代码,如果没有main会一直开启子进程,而子进程的申请是需要开辟内存以及申请pid等的。

 

 

进程间通讯

队列queue()

使用方法跟threading里的queue类似,但是不同进程间内存是不共享的,所以要用下面的方法

复制代码
from multiprocessing import Process, Queue

def f(q,n):
    q.put('hello')

def f1(q):
    print(q.get())
if __name__ == '__main__':
    q = Queue()
    for i in range(2):
        p = Process(target=f, args=(q,i))
        p.start()
    tp1 = Process(target=f1,args=(q,))
    tp2 = Process(target=f1, args=(q,))
    tp3 = Process(target=f1, args=(q,))
    tp1.start()
    tp2.start()
复制代码

要传入一个公共的queue来保证是同一个队列。

 

管道Pipes

Pipe()返回两个值(conn1,conn2),作为通讯的两个端。通过设置duplex参数来设置两个端口的功能,如果duplex参数为True(默认值),那么这个管道是全双工模式,也就是说conn1和conn2均可收发。duplex为False,conn1只负责接受消息,conn2只负责发送消息。

复制代码
from multiprocessing import Process, Pipe


def s(conn):
    conn.send('hello, how do you do')
    conn.close()

def r(conn):
    print(conn.recv())


if __name__ == '__main__':
    conn1, conn2 = Pipe()
    p1 = Process(target=s, args=(conn1,))
    p2 = Process(target=r, args=(conn2,))
    p1.start()
    p2.start()
复制代码

 

Managers实现进程之间的数据共享

manager支持 listdictNamespaceLockRLockSemaphoreBoundedSemaphoreConditionEventBarrierQueueValue,Array等类型的共享

复制代码
from multiprocessing import Process, Manager

def f(d, l,n):
    d[n] = '1'
    d['2'] = 2
    d[0.25] = None
    l.append(n)
    print(l)

if __name__ == '__main__':
    with Manager() as manager:
        d = manager.dict()
        l = manager.list(range(5))
        p_list = []
        for i in range(10):
            p = Process(target=f, args=(d, l,i))
            p.start()
            p_list.append(p)
        for res in p_list:
            res.join()

        print(d)
        print(l)
复制代码

待续



所属网站分类: 技术文章 > 博客

作者:iuie9493

链接:https://www.pythonheidong.com/blog/article/15167/04073451424d6d751328/

来源:python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

5 0
收藏该文
已收藏

评论内容:(最多支持255个字符)