首页  /  Python教程  /  进程通信  /  

进程通信

点击打开在线编译器,边学边练

        学习完如何创建进程之后,我们可以通过多次调用的方式创建多个进程,那么每个进程之间的信息是怎么样的,它们又是如何进行通信的,它们能否直接共用一些资源呢,下面我们通过一个例子来了解一下。

from multiprocessing import Process
number = 100
def change():#为拟创建的子进程1提供方法
    print('子进程1开始运行')
    global number
    number += 10
    print('把number加10等于:%d'%number)
    print('子进程1结束')
def changes():#为拟创建的子进程2提供方法
    print('子进程2开始运行')
    global number
    number += 20
    print('把number加20等于:%d'%number)
    print('子进程2结束')
if __name__ == '__main__':
    process_one = Process(target=change)
    process_one.start()#启动进程
    process_one.join()#等待进程执行结束
    process_two = Process(target=changes)
    process_two.start()#启动进程
    process_two.join()#等待进程执行结束
    print('number最后为:%d'%number)

        运行结果为:

子进程1开始运行
把number加10等于:110
子进程1结束
子进程2开始运行
把number加20等于:120
子进程2结束
number最后为:100

        我们通过输出结果可以看出,即使他们共用的是一个资源number,但是都没有影响number的最终数值,也就是第一个使用过的资源并没有被用在第二个进程当中,资源没有共享,如果要实现进程间通信,Python在multiprocessing模块中提供了Queue、pipes等多种方法来进行数据的交换,我们下面来学习一下使用队列Queue来完成进程间的通信。

    1. 队列

        学过数据结构的同学一定对这个词不陌生,队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,进行插入操作的端称为队尾,进行删除操作的端称为队头。

        我们也可以通过生活中的排队机制来理解一下队列,当一座桥只能允许一辆车通过的时候,那么新到来的车只能排在队伍的末尾来通过这座桥,而队列中间的车是无法直接离开桥的,只有等排在队头的车通过了之后才能过桥。

        如图:

 图片3.png

        甲刚刚从队头出队,那么紧接着乙可以出队,后续的继续等待,当甲出队之后,戊可以准备入队。

    2. 多进程队列

        在Python中,multiprocessing模块中存在Queue类帮我们实现多进程之间的数据交互,初始化一个Queue对象的方式为:my_queue = Queue(count),还有一些常用的方法:

        Queue.qsize():返回队列中的信息数量。

        Queue.empty():如果队列为空,则返回True,否则为false。由于多线程/多处理语义,这是不可靠的。

        Queue.full():如果队列已满,则返回true,否则返回false。

        Queue.put(obj[, block[, timeout]]):将obj放入队列中,如果可选参数块为True(默认值),超时为None(默认值),则必要时阻塞,直到空闲插槽可用为止。如果超时为正数,则为b 锁定最多超时秒并提高队列。

        Queue.get([block[, timeout]]) :从队列中移除并返回一个项。如果可选args块为True (默认值),超时为None(默认值)。

        还有更多的用法大家可以在Python文档中去进一步了解。

 图片4.png

        下面我们通过一个例子来实现多进程队列的通信,假设有一个停车场,有停车和开走车两个操作,下面我们要在程序中写两个子进程,其中一个进程往进程中停放车辆,另外一个子进程把车辆开出去,代码如下:

from multiprocessing import Process,Queue
import time
import datetime
#往停车场中停入车辆
def park(x):
    if not x.full():
        for i in range(5):
            car = '车辆'+str(i)
            x.put(car)
            print('停入:%s 时间:%s'%(car,datetime.datetime.now()))
#开走车辆
def drive(x):
    time.sleep(2)#休眠2s
    while not x.empty():
        print('开走:%s时间:%s'%(x.get(True,3),datetime.datetime.now()))
if __name__ == '__main__':
    x = Queue()#创建一个队列
    p = Process(target=park,args=(x,))#创建一个进程,并放入队列中
    d = Process(target=drive,args=(x,))#创建一个进程,并放入队列中
    p.start()#启动
    d.start()#启动
    p.join()
    d.join()

        输出结果如下:

停入:车辆0     时间:2020-02-10 10:48:01.290038
停入:车辆1     时间:2020-02-10 10:48:01.290038
停入:车辆2     时间:2020-02-10 10:48:01.290038
停入:车辆3     时间:2020-02-10 10:48:01.291037
停入:车辆4     时间:2020-02-10 10:48:01.291037
开走:车辆0     时间:2020-02-10 10:48:03.292486
开走:车辆1     时间:2020-02-10 10:48:03.292486
开走:车辆2     时间:2020-02-10 10:48:03.292486
开走:车辆3     时间:2020-02-10 10:48:03.292486
开走:车辆4     时间:2020-02-10 10:48:03.292486

        3. 总结

        学习完了这一节,进程和线程也就结束了,本章我们主要了解了如何创建他们,然后就是如何使用他们进行通信,另外我们还学习了线程安全和线程管理,这些内容对于操作系统而言是很重要的内容,想要了解更多的知识,可以去查看Python文档或者去查阅操作系统的相关书籍。

 



本文固定URL:https://www.dotcpp.com/course/303

上一课:创建进程
第一章 人生苦短,我用Python
第二章 Python基础语法
第三章 Python入门语法
第四章 Python核心语法
第五章 函数
第六章 面向对象编程
第七章 模块
第八章 异常处理和程序调试
第九章 文件及目录操作
第十章 GUI编程
第十一章 进程和线程
第十二章 数据库管理
第十三章 算法
第十四章 爬虫
第十五章 实战篇
第十六章 后记
Dotcpp在线编译      (登录可减少运行等待时间)