目录

Python进程间通信学习笔记

一、前言:

  • 我们在前面学习了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的进程间通信也没想象中复杂呢?

  • 喜欢就给我留言哦