创建多进程

  • 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. 16、生命周期-BeanPostProcessor原理

    16.生命周期-BeanPostProcessor原理 16.1 打断点运行postProcessBeforeInitialization 可以看到先执行的顺序为: applyBeanPostProc ...

  2. 快速了解AMD、CMD、CommonJS、ESM

    1.ES6 Module javascript在ES2015(ES6)中出现了语言层面的模块(module). ES6的模块既可以用于浏览器端,也可以用于服务器端(nodeJS). ES6模块是静态化 ...

  3. pyecharts v1 版本 学习笔记 散点图

    散点图 基本案例 from example.commons import Faker from pyecharts import options as opts from pyecharts.char ...

  4. 事务日志已满 请参阅sys.databases中的log_reuse_wait_desc列解决办法

    http://www.myexception.cn/sql-server/153219.html http://blog.csdn.net/kedingboy12345/article/details ...

  5. Java并发指南5:JMM中的final关键字解析

    本文转载自互联网,侵删   与前面介绍的锁和volatile相比较,对final域的读和写更像是普通的变量访问.对于final域,编译器和处理器要遵守两个重排序规则: 在构造函数内对一个final域的 ...

  6. 一、Linux的基础使用--登录、开关机与在线、命令的查询帮助

    目录 一.Linux的基础使用 1.1 X Window 与命令行模式的切换 1.2 命令行模式下命令的执行 1.3 修改支持语系 1.4 基础命令的操作 1.5 几个重要的热键[Tab].[Ctrl ...

  7. idhttp访问HTTPS

    idhttp访问HTTPS 访问一个 WEB 网站,如果采用 HTTP 的话,直接使用 TIdHTTP 这个控件,最简单的用法是: S := IdHTTP1.Get('www.qq.com'); 这里 ...

  8. BGP多线 有些BGP IP也会被极少数运营商劫持 取Ip逻辑

    小结: 1.租用的服务器只有一个IP,用户的访问路线是由路由器根据访客的实际访问速度选择最优访问路径,来选择访问的.而且不占用任何的服务器资源.服务器的上行和下行都是有路由器来选择最佳的路线,所以这样 ...

  9. Connection

    作用: * 获取执行sql语句对象 ** createStatement(): 获取Statement对象 ** prepareStatement(String sql): 获取预处理对象 ** pr ...

  10. 前端中关于HTML标签的属性for的理解

    First:<label>的说明:1.<label>标签为input元素定义标注(标识)2.label元素不会像用户呈现任何特殊的效果,仅作为显示扩展:不过,它为鼠标用户改进了 ...