Python进程间通信学习笔记

  发布日期:   2017-08-23
  最新修改:   2020-03-21
  阅读次数:   37 次

一、前言:

  • 我们在前面学习了python的多进程的创建及使用,是不是很Easy呢?
  • 但是,一旦涉及到多进程的使用,难免我们就会遇到多进程间通信的问题。
  • 本次我们就来学习多进程间的通信,其实也很Easy的哦。

二、Python 进程间通信方式一:Queue

Queue方法介绍

  • 1、Queue.qsize():返回当前队列包含的消息数量;

  • 2、Queue.empty():判断队列是否为空,空返回True,否则返回False ;

  • 3、Queue.full():判断队列是否满了,满返回True,否则返回False;

  • 4、Queue.get():取出队列中的一条消息且该消息从列队中移除,可传参超时时长。

  • 5、Queue.get_nowait():相当Queue.get(False),取不到值时触发异常:Empty;

  • 6、Queue.put():将一个值添加进数列,可传参超时时长。

  • 7、Queue.put_nowait():相当于Queue.get(False),当队列满了时报错:Full。

  • 示例代码:

      from multiprocessing import Queue,Process,Pool;
      import time,random
    
      # 创建列队,不传数字表示列队不限数量
      q = Queue()
      for i in range(10):
          q.put(i)
    
      def run_proc(name):
          while True:
              try:
                  p_v = q.get_nowait()
                  print('I am process %s,get value is :%d'%(name,p_v))
                  time.sleep(random.random())
              except Exception as e:
                  print(e);
                  break
    
      pool = Pool(3)
    
      for i in range(10):
          pool.apply_async(run_proc,(i,))
    
      pool.close()
      pool.join()
  • 结果输出为:

      I am process 0,get value is :0
      I am process 3,get value is :1
      I am process 4,get value is :2
      I am process 4,get value is :3
      I am process 0,get value is :4
      I am process 3,get value is :5
      I am process 4,get value is :6
      I am process 3,get value is :7
      I am process 3,get value is :8
      I am process 4,get value is :9

错误的方法

  • 假如我们想让进程往全局的集合中放入数据,是不是可行呢?

  • 示例代码:

      from multiprocessing import Queue,Process,Pool;
      import time,random
    
      global lst;
      lst = [];
    
      def run_proc(name,v):
              try:
                  global lst;
                  lst.append(v)
                  print(lst)
                  time.sleep(random.random())
              except Exception as e:
                  print(e);
    
      pool = Pool(2)
    
      for i in range(4):
          pool.apply_async(run_proc,(i,i,))
    
      pool.close()
      pool.join()
      print(lst)
  • 输出结果:

      [0]
      [1]
      [1, 2]
      [0, 3]
      []
  • 结果说明:子进程结束后,我们发现,lst还是空的,为什么呢?因为每个进程都有属于自己的存储空间,自然全局变量也是进程自己独有的,所以想通过全局变量来实现进程间数据的存储和读取是不可行的,此时我们也可以通过Queue来实现。

  • 代码修改如下:

      from multiprocessing import Queue,Process,Pool;
      import time,random
    
      q = Queue();
    
      def run_proc(name,v):
              try:
                  q.put(v)
                  time.sleep(random.random())
              except Exception as e:
                  print(e);
    
      pool = Pool(2)
    
      for i in range(4):
          pool.apply_async(run_proc,(i,i,))
    
      pool.close()
      pool.join()
    
      v = q.get();
      while v is not  None:
          print(v);
          v = q.get()
  • 结果输出如下:

      0
      1
      2
      3

-可以发现,通过queue我们就很容易实现进程间数据的存储了。

三、进程间通信方式二:Pipe

  • Pipe管道,可以是单向和双向,默认为双向。双向Pipe允许两端的进即可以发送又可以接受;单向的Pipe只允许前面的端口用于接收,后面的端口用于发送。

  • 我们在创建Pipe时传入False即可创建单向管道。

  • 示例代码(通过管道,一个进程内发送数据,一个进程内接收数据):

      def proc_one(pipe):
          s = 'Hello,I am proc_one'
        pipe.send(s)
          print("proc_one send data is: %s"%s)
    
      def proc_two(pipe):
          while True:
              print("proc_two recieve data is:", pipe.recv())
    
      if __name__ == "__main__":
          pipe = Pipe()
          p1 = Process(target=proc_one, args=(pipe[0],))
          p2 = Process(target=proc_two, args=(pipe[1],))
          p1.start()
          p2.start()
          p1.join()
          # 限制执行时间描述,不设置则proc_two中会死循环
        p2.join(2)
          print('run end')
  • 运行加过为:

      proc_one send data is: Hello,I am proc_one
      proc_two recieve data is: Hello,I am proc_one
      run end
  • 可以看到,我们很容易的就实现了进程间通信。

四、强大的Manage支持管道通信

  • Python中提供了Manage专门用来做数据共享,Manage其支持的数据类型有: Value,Array,list, dict,Queue, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event等

  • 示例代码:

      def proc_one(lst):
          s = 'Hello,I am proc_one'
        lst.append(s);
          print("proc_one add data is: %s"%s)
    
      def proc_two(lst):
          s = 'Hello,I am proc_two'
        lst.append(s);
          print("proc_two add data is: %s" % s)
    
      if __name__ == "__main__":
          m = Manager();
          lst = m.list();
          p1 = Process(target=proc_one, args=(lst,))
          p2 = Process(target=proc_two, args=(lst,))
          p1.start()
          p2.start()
          p1.join()
          # 限制执行时间描述,不设置则proc_two中会死循环
        p2.join(2)
          print('run end')
          print(lst)
  • 运行结果为:

      proc_one add data is: Hello,I am proc_one
      proc_two add data is: Hello,I am proc_two
      run end
      ['Hello,I am proc_one', 'Hello,I am proc_two']
  • Ok,其它的类型我这就不做演示了,是不是觉得其实Python的进程间通信也没想象中复杂呢?

  • 喜欢就给我留言哦


   转载规则

《Python进程间通信学习笔记字》GajAngels 采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。