python进程间通信(一)

python 的之间有时需要通信,操作系统提供了很多机制来实现进程间的通信。

1. Queue的使用

  • from multiprocessing import Queue (可以用于多进程,但不能用于进程池)

multiprocessing模块的Queue如果用与Pool创建的进程,会报错

RuntimeError: Queue objects should only be shared between processes through inheritance.

看一个实例:

from multiprocessing import Process, Queue
import os, time, random

# 写数据进程执行的代码:
def write(q):
   for value in ['A', 'B', 'C']:
       print 'Put %s to queue...' % value
       q.put(value)
       time.sleep(random.random())

# 读数据进程执行的代码:
def read(q):
   while True:
       if not q.empty():
           value = q.get(True)
           print 'Get %s from queue.' % value
           time.sleep(random.random())
       else:
           break

if __name__=='__main__':

   # 父进程创建Queue,并传给各个子进程:
   q = Queue()
   pw = Process(target=write, args=(q,))
   pr = Process(target=read, args=(q,))
   # 启动子进程pw,写入:
   pw.start()    
   # 等待pw结束:
   pw.join()
   # 启动子进程pr,读取:
   pr.start()
   pr.join()
   # pr进程里是死循环,无法等待其结束,只能强行终止:
   print ''
   print '所有数据都写入并且读完'
  • from multiprocessing import Manager(可以用于Pool创建的进程池)

Manager().Queue()可以用与multiprocessing创建的进程和Pool创建的进程中.
下面的案例演示进程池(Pool)之间的通信

#coding=utf-8

#修改import中的Queue为Manager
from multiprocessing import Manager,Pool
import os,time,random

def reader(q):
    print("reader启动(%s),父进程为(%s)"%(os.getpid(),os.getppid()))
    for i in range(q.qsize()):
        print("reader从Queue获取到消息:%s"%q.get(True))

def writer(q):
    print("writer启动(%s),父进程为(%s)"%(os.getpid(),os.getppid()))
    for i in ["A", "B", "C", "D"]:
        q.put(i)

if __name__=="__main__":
    print("(%s) start"%os.getpid())
    q=Manager().Queue() #使用Manager中的Queue来初始化
    po=Pool()
    #使用阻塞模式创建进程,这样就不需要在reader中使用死循环了,可以让writer完全执行完成后,再用reader去读取
    po.apply(writer,(q,))
    po.apply(reader,(q,))
    po.close()
    po.join()
    print("(%s) End"%os.getpid())

2. Pipe的使用

  • Pipe常用于两个进程,两个进程分别位于管道的两端.
  • Pipe方法返回(conn1,conn2)代表一个管道的两个端,Pipe方法有duplex参数,默认为True,即全双工模式,若为FALSE,conn1只负责接收信息,conn2负责发送,
  • send和recv方法分别为发送和接收信息。
    下面的案例演示如何使用Pipe
# coding:utf-8

import multiprocessing
import os,time,random

#写数据进程执行的代码
def proc_send(pipe):
    #print 'Process is write....'
    for url in ["A", "B", "C", "D"]:

        print 'Process is send :%s' %url
        pipe.send(url)
        time.sleep(random.random())

#读数据进程的代码
def proc_recv(pipe):
    while True:
        print('Process rev:%s' %pipe.recv())
        time.sleep(random.random())

if __name__ == '__main__':
    #父进程创建pipe,并传给各个子进程
    s_pipe, r_pipe = multiprocessing.Pipe()
    
    p1 = multiprocessing.Process(target=proc_send,args=(s_pipe,))
    p2 = multiprocessing.Process(target=proc_recv,args=(r_pipe,))
    #启动子进程,写入
    p1.start()
    p2.start()

    p1.join()
    p2.terminate()

4. 多进程和全局变量

共享变量不适用于多进程,进程间的变量是互相隔离的,子进程的全局变量是完全复制一份父进程的数据,对子进程的全局变量修改完全影响不到其他进程的全局变量.
下面的案例演示的是多进程对全局变量的影响

def producer(a):
    a += 1
    time.sleep(2)
 
def consumer(a):
    time.sleep(3)
    data = a
    print(data)
 
if __name__ == "__main__":
    a = 1
    my_producer = Process(target=producer,args=(a,))
    my_consumer = Process(target=consumer,args=(a,))
    my_producer.start()
    my_consumer.start()
    my_producer.join()
    my_consumer.join()

结果

1

Process finished with exit code 0

总结:在多线程中,我们可以比较容易地共享资源,比如使用全局变量或者传递参数。在多进程情况下,由于每个进程有自己独立的内存空间,以上方法并不合适。此时我们可以通过以上方法共享全局变量.实际我们也可以通过共享内存和Manager的方法来共享资源.有时间了再接着看其他方式.

猜你喜欢

转载自blog.csdn.net/weixin_35762183/article/details/88636969