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


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

    进程

    由于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)

    待续

  • 相关阅读:
    如何使用Jquery 引入css文件
    html如何绘制带尖角(三角)的矩形
    让HTML标签、DIV、SPAN拥有focus事件和blur事件,聚焦和失焦
    html如何引用另一个html的内容
    HTML中块级元素与内联元素有什么区别 ?
    一个js文件如何加载另外一个js文件
    在线工具-程序员的工具箱-在线Cron表达式生成器
    oracle fm格式化
    html如何让label在div中的垂直方向居中显示?
    服务发现框架选型: Consul、Zookeeper还是etcd ?
  • 原文地址:https://www.cnblogs.com/smilepup-hhr/p/10584140.html
Copyright © 2020-2023  润新知