创建多进程

  • windows:进程、线程
  • linux:进程、线程(做了进程通信的多进程实现的线程)
  • 进程之间内存彼此独立,不管是父子进程还是单个独立进程
  • multiprocessing:Process 创建多进程python内置的模块
  • current_process().name 返回的是当前的进程是哪个
  • from multiprocessing import process,current_process
    def work():
    print('我是进程:%s' % current_process().name)
    work() 运行结果:我是进程:MainProcess
  • dir(current_process())  :current_process的内置函数
    • ['_Popen', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_bootstrap', '_config', '_identity',
      '_name', '_parent_pid', '_popen', 'authkey', 'daemon', 'exitcode', 'ident', 'is_alive', 'join', 'name', 'pid', 'run', 'sentinel', 'start', 'terminate']
    • current_process().pid:是打印当前进程id:返回的是当前进程的id
    • current_process().name:返回的是当前的进程名称
    • current_process().terminate:直接终止进程
    • current_process().is_alive():返回进程的存活状态 True/False
    • current_process().exitcode:0代表进程死亡 None代表进程运行
    • current_process().ident:和pid类似
  • 创建多进程其实就是把一个任务(工作函数)绑定在一个子进程上,然后将任务分配多个多个子进程上去执行
  • 大家记得一定要把多进程的创建放在main函数里面
  • help(process)  :创建多进程函数帮助文档,target:调用函数名 ,name:子进程命名,args:元组传参,kwargs:字典传参
    •  __init__(self, group=None, target=None, name=None, args=(), kwargs={}, *
      , daemon=None)
  • p1 = Process(target=func,name=,args=(),kwargs={}):创建子进程传参模型
    • p1.start():开启进程
    • p1.join():回收子进程
    • p1.name :#获取进程名字
    • p1.pid :获取进程ID之
    • p1.terminate :直接终止进程
    • p1.is_alive() :返回进程的存活状态 True/False
    • p1.exitcode: 0代表进程死亡 None代表进程运行
    • p1.ident :和pid类似
  • import sys  sys.stdout.flush() #刷新缓存区
  • #创建多进程1.py
    from multiprocessing import Process,current_process
    import sys
    def work():
    print('我是子进程:%s进程id:%s' % (current_process().name,current_process().pid))
    sys.stdout.flush() #刷新缓存
    def main():
    print('当前父进程:%s进程id:%s' % (current_process().name,current_process().pid))
    p1 = Process(target=work,name='子进程一号') #创建子进程
    p2 = Process(target=work,name='子进程二号') #创建子进程
    p1.start() #开启进程
    p2.start()
    print(p1.name,p1.pid,p1.is_alive(),p1.exitcode,p1.ident)
    print(p2.name,p2.pid,p2.is_alive(),p2.exitcode,p2.ident)
    p1.join() #回收子进程
    p2.join()
    if __name__ == "__main__":
    main()
    ##当前进程数是3个,一个父进程两个子进程

    运行结果:

    当前父进程:MainProcess进程id:134216
    子进程一号 129748 True None 129748
    子进程二号 134780 True None 134780
    我是子进程:子进程一号进程id:129748
    我是子进程:子进程二号进程id:134780
  • #创建多进程2.py
    from multiprocessing import Process,current_process
    import sys
    def work(a,char):
    print('-----------------------------')
    print('当前子进程:%s' % current_process().name)
    a[0] = char
    print('当前子进程修改完毕:',a)
    sys.stdout.flush() #刷新缓存
    def main():
    a = [1,2,3]
    print('当前父进程:',a)
    p1 = Process(target=work,name='进程1',args=(a,'a'))
    p2 = Process(target=work,name='进程2',args=(a,'zhang'))
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    if __name__ == "__main__":
    main()

    运行结果:

    当前父进程: [1, 2, 3]
    -----------------------------
    当前子进程:进程1
    当前子进程修改完毕: ['a', 2, 3]
    -----------------------------
    当前子进程:进程2
    当前子进程修改完毕: ['zhang', 2, 3]

僵尸进程

  • 如果父进程没有对子进程合理回收
    • 父进程没有在子进程工作结束之后立即回收
    • PCB控制块 PID继续占用  僵尸进程
  • 子进程结束 ,父进程依然存活
  • from multiprocessing import Process,current_process
    from time import sleep
    def work():
    print('子进程开始了')
    print('PID:%s' % current_process().pid )
    print('子进程结束了')
    def main():
    p = Process(target=work)
    p.start() #父进程开启了子进程
    #p.join() #回收子进程 或者忘记回收
    #父进程退出了
    sleep(10) #退出
    #p.join()
    if __name__ == '__main__':
    main()  

孤儿进程

  • Python代码中如果在父进程没有明确写出join回收子进程,在父进程结束之后,父进程回自动帮助回收
  • kill -9 pid  强制杀死

多进程通讯--Queue

  • 》》》》Python中任何普通的基础数据类型,都不可以在多进程下通信 
  • **Queue**(size):共享通讯队列,阻塞的行为,默认为阻塞,block=False设置为非阻塞
    • 值满了不能放:q.put(block=True) 默认为True
    • 值空了不能取,会一直等:q.get(block=True)
    • 当修改了拿取的方式为非阻塞,那么数据在取不到或者立即放不进去的时候会直接报错
      • queue.Full 满了
      • queue.Empty 空的
    • q.empty():判断队列是否为空
    • q.full():判断队列是否为满
    • q.qsize():返回队列数据个数
  • #创建共享队列1.py
    from multiprocessing import Process,current_process,Queue
    def main():
    q = Queue() #创建共享队列
    print('当前父进程:',q)
    for var in range(5):
    q.put(var)
    print(q.get())
    print(q.get())
    print(q.get())
    print(q.get())
    print(q.get())
    if __name__ == "__main__":
    main()

    运行结果:

    当前父进程: <multiprocessing.queues.Queue object at 0x000000000277A2E8>
    0
    1
    2
    3
    4    
  • #创建共享队列2.py
    from multiprocessing import Process,current_process,Queue
    def product(q):#生产数据
    for var in range(5):
    q.put(var,block=False)#非阻塞
    def custom(q):#消费数据
    for var in range(5):
    i = q.get(block=False)#非阻塞
    print('%s取到的数据:%s' % (current_process().name,i))
    def main():
    q = Queue(5) #创建共享队列
    p1 = Process(target=product,name='生产进程',args=(q,))
    p2 = Process(target=custom,name='消费进程',args=(q,))
    p1.start(),p2.start(),p1.join(),p2.join()
    if __name__ == "__main__":
    main()

    运行结果:

    消费进程取到的数据:0
    消费进程取到的数据:1
    消费进程取到的数据:2
    消费进程取到的数据:3
    消费进程取到的数据:4   
  • #创建共享队列3.py
    from multiprocessing import Process,Queue,current_process
    from time import sleep
    import sys
    def product(q):#某个进程生产数据
    for var in range(10):
    q.put(var)
    sleep(1)
    def custom(q):#这个进程消费数据
    for var in range(5):
    i = q.get()
    print('%s进程取到的数据:%s' % (current_process().name,i))
    sys.stdout.flush()
    def main():
    q = Queue() #共享队列
    p1 = Process(target=product,args=(q,))
    p2 = Process(target=custom,name='消费进程1',args=(q,))
    p3 = Process(target=custom,name='消费进程2',args=(q,))
    p1.start(),p2.start(),p3.start(),p1.join(),p2.join(),p3.join()
    print('------------')
    if __name__ == '__main__':
    main()

    运行结果:

    消费进程1进程取到的数据:0
    消费进程1进程取到的数据:1
    消费进程2进程取到的数据:2
    消费进程1进程取到的数据:3
    消费进程2进程取到的数据:4
    消费进程1进程取到的数据:5
    消费进程2进程取到的数据:6
    消费进程1进程取到的数据:7
    消费进程2进程取到的数据:8
    消费进程2进程取到的数据:9
    ------------
  • 下面的是子进程while循环取值,在阻塞行为下值空了不能取,会一直等,那么如何才能不让它退出,也不报错呢?如果改为非阻塞那么值空了就会报错,看下面的方法
  • from multiprocessing import Process,Queue,current_process
    from time import sleep
    import sys
    def product(q,sig):#某个进程生产数据
    for var in range(8):
    sig.put(True) #每次生产,都放一个True
    q.put(var)
    sleep(1)
    else:
    sig.put(False)
    def custom(q,sig):#这个进程消费数据
    while True:
    if sig.get(): #代表还有数据要生产
    i = q.get()
    print('%s进程取到的数据:%s' % (current_process().name,i))
    sys.stdout.flush()
    else: #没有数据要生产了
    print('子进程结束,数据生产完毕')
    sig.put(False)
    break
    def main():
    q = Queue() #共享队列
    sig = Queue()
    p1 = Process(target=product,args=(q,sig))
    p2 = Process(target=custom,name='消费进程1',args=(q,sig))
    p3 = Process(target=custom,name='消费进程2',args=(q,sig))
    p1.start(),p2.start(),p3.start(),p1.join(),p3.join(),p2.join()
    print('------------')
    if __name__ == '__main__':
    main()

    运行结果为:

    消费进程1进程取到的数据:0
    消费进程1进程取到的数据:1
    消费进程2进程取到的数据:2
    消费进程1进程取到的数据:3
    消费进程2进程取到的数据:4
    消费进程1进程取到的数据:5
    消费进程2进程取到的数据:6
    消费进程1进程取到的数据:7
    消费进程2:子进程结束,数据生产完毕
    消费进程1:子进程结束,数据生产完毕
    ------------

多进程通讯--pipe

  • Pipe:管道两端, duplex=True 存储的都是pickle数据类型
  • left,right = Pipe(duplex)
  • pickle = p.recv() 向管道这一侧取出来
  • p.send(pickle) 向管道另一侧去发
  • 管道只能存放和拿取出来pickle数据类型
    • pickle 二进制数据 Python中维持数据类型保存 解析
    • pickle.loads:解析数据
    • pickle.dumps:封装为二进制
  • 管道在使用的时候,是有两端的,要注意使用顺序
  • 首先:多个进程可以享用同一个端,也就是一个管道支持多个进程通信,非常安全的操作(要记住)
  • #pipe 单个消费者生产者模型
    from multiprocessing import Process,current_process,Pipe
    import pickle
    def work_a(p):
    for var in range(5):
    p.send(pickle.dumps(var))
    print('%s:生产数据|%s' % (current_process().name,var))
    def work_b(p):
    for var in range(5):
    pickle_obj = pickle.loads(p.recv()) #阻塞
    print('%s:消费数据|%s' % (current_process().name,pickle_obj))
    def main():
    a,b = Pipe() #创建管道
    p1 = Process(target=work_a,name='生产者',kwargs={'p':a})
    p2 = Process(target=work_b,name='消费者',kwargs={'p':b})
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    if __name__ == "__main__":
    main()
  • 运行结果:

    生产者:生产数据|0
    生产者:生产数据|1
    生产者:生产数据|2
    生产者:生产数据|3
    生产者:生产数据|4
    消费者:消费数据|0
    消费者:消费数据|1
    消费者:消费数据|2
    消费者:消费数据|3
    消费者:消费数据|4   
  • #pipe 多个消费者生产者模型  一个消费者只消费一个数据,公司里面常用的模型,一个管道支持多个进程通信,非常安全的操作
    from multiprocessing import Process,current_process,Pipe
    import pickle
    def work_a(p):
    for var in range(5):
    p.send(pickle.dumps(var))
    print('%s:生产数据|%s' % (current_process().name,var))
    def work_b(p):
    pickle_obj = pickle.loads(p.recv()) #阻塞
    print('%s:消费数据|%s' % (current_process().name,pickle_obj))
    def main():
    a,b = Pipe() #创建管道
    p1 = Process(target=work_a,name='生产者',args=(a,))
    p2 = [] #消费者进程队列
    for var in range(5):
    p2.append(Process(target=work_b,name='消费者%d' % var,args=(b,)))
    p1.start() #下开启生产者
    for var in p2:
    var.start()
    p1.join()
    for var in p2:
    var.join()
    if __name__ == "__main__":
    main()

    运行结果:

    生产者:生产数据|0
    生产者:生产数据|1
    生产者:生产数据|2
    生产者:生产数据|3
    生产者:生产数据|4
    消费者1:消费数据|0
    消费者2:消费数据|1
    消费者3:消费数据|2
    消费者0:消费数据|3
    消费者4:消费数据|4    

多进程状态通讯--Event

  • from multiprocessing import Event
  • e = Event() e:状态实例
  • e.set() #设置当前的实例状态为True
  • e.clear() #设置当前的实例状态为False
  • e.wait()
    • False:阻塞等待
    • True:向下执行
  • from multiprocessing import Event,Process,current_process
    from time import sleep
    import sys
    def work(e):
    print('%s已开启' % current_process().name)
    sys.stdout.flush() #刷新输出缓冲区,立竿见影看到打印
    e.wait() #Sleep 可中断睡眠
    print('%s正式开始工作' % current_process().name)
    sys.stdout.flush()
    print('%s|pid:%s' % (current_process().name,current_process().pid))
    def main():
    print('主进程开启')
    e = Event()
    p1 = Process(target=work,name='进程1',args=(e,))
    p2 = Process(target=work,name='进程2',args=(e,))
    p1.start() #进程已经开启
    p2.start()
    for var in range(3):
    print(var)
    sleep(1) #- e.wait()
    e.set() #信号变True
    p1.join()
    p2.join()
    if __name__ == '__main__':
    main()  
  • 运行结果:

    主进程开启
    0
    进程2已开启
    进程1已开启
    1
    2
    进程1正式开始工作
    进程2正式开始工作
    进程1|pid:3108
    进程2|pid:6068

      

      

      

 

39.创建多进程及进程通讯 -- Queue--Pipe--Event的更多相关文章

  1. 多进程操作-进程队列multiprocess.Queue的使用

    一.ipc机制 进程通讯 管道:pipe 基于共享的内存空间 队列:pipe+锁 queue 下面拿代码来实现Queue如何使用: 案例一: from multiprocessing import Q ...

  2. 进程之间的通讯Queue简单应用

    #进程间通讯--Queue #Process有时需要通信的,操作系统提供了很多机制来实现进程之间的通讯 #而Queue就是其中一个 #1.Queue的使用 #可以使用multiprocessing模块 ...

  3. Python创建多进程,用Queue传递信息

    创建10个进程,分别计算0到1000各个区间的和,主进程汇总 __author__ = 'Administrator' # -*- coding:utf-8 -*- ''' @author:qiush ...

  4. python网络编程-进程间数据通信(Queue,Pipe ,managers)

    一:进程间数据交换方法 不同进程间内存是不共享的,要想实现两个进程间的数据交换,可以用以下方法: Queue,Pipe ,managers 1)Queue,使用方法跟threading里的queue差 ...

  5. 结合process进程,实现进程之间的通讯Queue,稍微复杂的运用

    #在父进程中创建两个子进程,一个往Queue写数据,一个从Queue里读数据 from multiprocessing import Queue,Process import time,random ...

  6. python并发编程02 /多进程、进程的创建、进程PID、join方法、进程对象属性、守护进程

    python并发编程02 /多进程.进程的创建.进程PID.join方法.进程对象属性.守护进程 目录 python并发编程02 /多进程.进程的创建.进程PID.join方法.进程对象属性.守护进程 ...

  7. 进程同步控制(锁,信号量,事件), 进程通讯(队列和管道,生产者消费者模型) 数据共享(进程池和mutiprocess.Pool模块)

    参考博客 https://www.cnblogs.com/xiao987334176/p/9025072.html#autoid-1-1-0 进程同步(multiprocess.Lock.Semaph ...

  8. Python 多进程和进程池

    一,前言 进程:是程序,资源集合,进程控制块组成,是最小的资源单位 特点:就对Python而言,可以实现真正的并行效果 缺点:进程切换很容易消耗cpu资源,进程之间的通信相对线程来说比较麻烦 线程:是 ...

  9. python 守护进程、同步锁、信号量、事件、进程通信Queue

    一.守护进程 1.主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes ...

随机推荐

  1. python的logging日志模块(二)

    晚上比较懒,直接搬砖了. 1.简单的将日志打印到屏幕   import logging logging.debug('This is debug message') logging.info('Thi ...

  2. [Functional Programming] liftA2 and converge

    Sometimes I am confused with 'liftA2' and 'converge' functions. Main difference between those is tha ...

  3. HDU 6141 - I am your Father! | 2017 Multi-University Training Contest 8

    思路来自 FXXL 最小树形图模板用kuangbin的 /* HDU 6141 - I am your Father! [ 最小树形图 ] | 2017 Multi-University Traini ...

  4. Codeforces Round #442 (Div. 2) B题【一道模拟题QAQ】

    B. Nikita and string One day Nikita found the string containing letters "a" and "b&qu ...

  5. Ubuntu14.04 打开关闭图形桌面

    使用 Ctrl+Alt+t 打开命令行界面 #关闭桌面 sudo service lightdm stop #恢复桌面 sudo service lightdm start Ctrl+Alt+F1 可 ...

  6. 菜单栏伸缩(附jquery-1.12.1.js)

    Css: <style type="text/css"> .leftMenu { min-width:220px; width:268px; margin:40px a ...

  7. 第二章 c语言概述

    一.#include指令和头文件 1.#include C预处理指令,C编译器在编译前对源代码做一些准备工作 2.stdio.h标准输入输出头文件,提供了关于输入输出的信息供编译器使用 头文件包含了建 ...

  8. SpringMVC返回Map类型转换成JSON失败

    错误信息:WARN DefaultHandlerExceptionResolver:380 - Failed to write HTTP message: org.springframework.ht ...

  9. Flutter移动电商实战 --(24)Provide状态管理基础

    Flutter | 状态管理特别篇 —— Provide:https://juejin.im/post/5c6d4b52f265da2dc675b407?tdsourcetag=s_pcqq_aiom ...

  10. <JavaScript> 稳妥构造函数模式与工厂模式的区别

    稳妥构造函数模式的代码应该是这样的: function Person(name, age, job) { var o = new Object(); // private members var na ...