Python实现进程同步和通信
Python实现进程同步和通信
如之前创建多进程的例子
# -*- coding:utf-8 -*-
from multiprocessing import Process,Pool
import os,timedef run_proc(name): ##定义一个函数用于进程调用for i in range(5): time.sleep(0.2) #休眠0.2秒print 'Run child process %s (%s)' % (name, os.getpid())
#执行一次该函数共需1秒的时间if __name__ =='__main__': #执行主进程print 'Run the main process (%s).' % (os.getpid())mainStart = time.time() #记录主进程开始的时间p = Pool(8) #开辟进程池for i in range(16): #开辟14个进程p.apply_async(run_proc,args=('Process'+str(i),))#每个进程都调用run_proc函数,#args表示给该函数传递的参数。print 'Waiting for all subprocesses done ...'p.close() #关闭进程池p.join() #等待开辟的所有进程执行完后,主进程才继续往下执行print 'All subprocesses done'mainEnd = time.time() #记录主进程结束时间print 'All process ran %0.2f seconds.' % (mainEnd-mainStart) #主进程执行时间
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
运行结果:
Run the main process (36652).
Waiting for all subprocesses done …
Run child process Process0 (36708)Run child process Process1 (36748)Run child process Process3 (36736)
Run child process Process2 (36716)
Run child process Process4 (36768)
如第3行的输出,偶尔会出现这样不如意的输入格式,为什么呢?
原因是多个进程争用打印输出资源的结果。前一个进程为来得急输出换行符,该资源就切换给了另一个进程使用,致使两个进程输出在同一行上,而前一个进程的换行符在下一次获得资源时才打印输出。
Lock
为了避免这种情况,需在进程进入临界区(使进程进入临界资源的那段代码,称为临界区)时加锁。
可以向如下这样添加锁后看看执行效果:
# -*- coding:utf-8 -*-lock = Lock() #申明一个全局的lock对象
def run_proc(name):global lock #引用全局锁for i in range(5):time.sleep(0.2)lock.acquire() #申请锁print 'Run child process %s (%s)' % (name, os.getpid())lock.release() #释放锁
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
Semaphore
Semaphore为信号量机制。当共享的资源拥有多个时,可用Semaphore来实现进程同步。其用法和Lock差不多,s = Semaphore(N),每执行一次s.acquire(),该资源的可用个数将减少1,当资源个数已为0时,就进入阻塞;每执行一次s.release(),占用的资源被释放,该资源的可用个数增加1。
多进程的通信(信息交互)
不同进程之间进行数据交互,可能不少刚开始接触多进程的同学会想到共享全局变量的方式,这样通过向全局变量写入和读取信息便能实现信息交互。但是很遗憾,并不能这样实现。具体原因,看这篇文章。
下面通过例子,加深对那篇文章的理解:
# -*- coding:utf-8 -*-
from multiprocessing import Process, Pool
import os
import timeL1 = [1, 2, 3]def add(a, b):global L1L1 += range(a, b)print L1if __name__ == '__main__':p1 = Process(target=add, args=(20, 30))p2 = Process(target=add, args=(30, 40))p1.start()p2.start()p1.join()p2.join()print L1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
输出结果:
[1, 2, 3, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
[1, 2, 3, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39]
[1, 2, 3]
该程序的原本目的是想将两个子进程生成的列表加到全局变量L1中,但用该方法并不能达到想要的效果。既然不能通过全局变量来实现不同进程间的信息交互,那有什么办法呢。
mutiprocessing为我们可以通过Queue和Pipe来实现进程间的通信。
Queue
按上面的例子通过Queue来实现:
# -*- coding:utf-8 -*-
from multiprocessing import Process, Queue, LockL = [1, 2, 3]def add(q, lock, a, b):lock.acquire() # 加锁避免写入时出现不可预知的错误L1 = range(a, b)lock.release()q.put(L1)print L1if __name__ == '__main__':q = Queue()lock = Lock()p1 = Process(target=add, args=(q, lock, 20, 30))p2 = Process(target=add, args=(q, lock, 30, 40))p1.start()p2.start()p1.join()p2.join()L += q.get() + q.get()print L
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
执行结果:
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
[30, 31, 32, 33, 34, 35, 36, 37, 38, 39]
[1, 2, 3, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39]
下面介绍Queue的常用方法:
- 定义时可用q = Queue(maxsize = 10)来指定队列的长度,默认时或maxsize值小于1时队列为无限长度。
- q.put(item)方法向队列放入元素,其还有一个可选参数block,默认为True,此时若队列已满则会阻塞等待,直到有空闲位置。而当black值为 False,在该情况下就会抛出Full异 常
- Queue是不可迭代的对象,不能通过for循环取值,取值时每次调用q.get()方法。同样也有可选参数block,默认为True,若此时队列为空则会阻塞等待。而black值为False时,在该情况下就会抛出Empty异常
- Queue.qsize() 返回队列的大小
- Queue.empty() 如果队列为空,返回True,反之False
- Queue.full() 如果队列满了,返回True,反之False
- Queue.get([block[, timeout]]) 获取队列,timeout等待时间Queue.get_nowait() 相当Queue.get(False) 非阻塞 Queue.put(item) 写入队列,timeout等待时间
- Queue.put_nowait(item) 相当Queue.put(item, False)
Pipe
Pipe管道,可以是单向(half-duplex),也可以是双向(duplex)。我们通过mutiprocessing.Pipe(duplex=False)创建单向管道 (默认为双向)。双向Pipe允许两端的进即可以发送又可以接受;单向的Pipe只允许前面的端口用于接收,后面的端口用于发送。
下面给出例子:
# -*- coding:utf-8 -*-
from multiprocessing import Process, Pipedef proc1(pipe):s = 'Hello,This is proc1'pipe.send(s)def proc2(pipe):while True:print "proc2 recieve:", pipe.recv()if __name__ == "__main__":pipe = Pipe()p1 = Process(target=proc1, args=(pipe[0],))p2 = Process(target=proc2, args=(pipe[1],))p1.start()p2.start()p1.join()p2.join(2) #限制执行时间最多为2秒print '\nend all processes.'
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
执行结果如下:
proc2 recieve: Hello,This is proc1
proc2 recieve:
end all processes.
当第二行输出后,因为管道中没有数据传来,Proc2处于阻塞状态,2秒后被强制结束。
以下是单向管道的例子,注意pipe[0],pipe[1]的分配。
# -*- coding:utf-8 -*-
from multiprocessing import Process, Pipedef proc1(pipe):s = 'Hello,This is proc1'pipe.send(s)def proc2(pipe):while True:print "proc2 recieve:", pipe.recv()if __name__ == "__main__":pipe = Pipe(duplex=False)p1 = Process(target=proc1, args=(pipe[1],)) #pipe[1]为发送端p2 = Process(target=proc2, args=(pipe[0],)) #pipe[0]为接收端p1.start()p2.start()p1.join()p2.join(2) # 限制执行时间最多为2秒print '\nend all processes.'
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
执行结果同上。
强大的Manage
Queue和Pipe实现的数据共享方式只支持两种结构 Value 和 Array。Python中提供了强大的Manage专门用来做数据共享,其支持的类型非常多,包括: Value,Array,list, dict,Queue, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event等
其用法如下:
from multiprocessing import Process, Manager
def func(dt, lt):for i in range(10):key = 'arg' + str(i)dt[key] = i * ilt += range(11, 16)if __name__ == "__main__":manager = Manager()dt = manager.dict()lt = manager.list()p = Process(target=func, args=(dt, lt))p.start()p.join()print dt, '\n', lt
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
执行结果:
{‘arg8’: 64, ‘arg9’: 81, ‘arg0’: 0, ‘arg1’: 1, ‘arg2’: 4, ‘arg3’: 9, ‘arg4’: 16, ‘arg5’: 25, ‘arg6’: 36, ‘arg7’: 49}
[11, 12, 13, 14, 15]
Python实现进程同步和通信相关推荐
- python实现STM32单片机通信
python实现STM32单片机通信 注意事项 注意事项 Python3中的encode('unicode-escape')和encode('raw_unicode_escape')区别与联系 htt ...
- python rs232_使用Python進行RS-232通信返回垃圾信息
我最近試圖通過RS-232連接控制OceanOptics HR4000光譜儀.我已經使用串行控制檯Termite測試了串行命令(這裏提供:http://www.oceanoptics.com/tech ...
- python中select模块_基于python select.select模块通信的实例讲解 如何用python写个串口通信的程序...
python socket怎么利用select实现双工通信 方法: Before : 0000000000000000000000000000000000000000 After pack: 0100 ...
- python多进程之间的通信:消息队列Queue
python中进程的通信:消息队列. 我们知道进程是互相独立的,各自运行在自己独立的内存空间. 所以进程之间不共享任何变量. 我们要想进程之间互相通信,传送一些东西怎么办? 需要用到消息队列!! 进程 ...
- USB to TTL python 本地测试串口通信
手头上有个 USB to TTL CH340 型号的,想在本地用 python 测试下串口通信. 硬件准备 首先是 USB to TTL 元件,找个跳线帽将 TXD 和 RXD 针脚相连,插到电脑上 ...
- 2020-10-29 实验四 进程同步与通信
实验四 进程同步与通信 一.实验目的: 二.实验环境: 三.实验内容: 四.心得体会: 一.实验目的: 1. 掌握基本的同步与互斥算法,理解P,V操作. 2. 理解生产者消费者模型,了解其它典型的同步 ...
- python实现socket简单通信
python实现socket简单通信 首先先来简单介绍下socket: (具体更详细介绍的可以在网上找找,都讲得非常详细),这里主要是我自己的一些理解. socket是在应用层与传输层之间的一个抽象层 ...
- Python中线程间通信
Python中线程间通信 一.前言 二.什么是互斥锁 三.使用互斥锁 四.使用队列在线程间通信 五.关于线程需要注意的两点 一.前言 我们已经知道进程之间不能直接共享信息,那么线程之间可以共享信息 ...
- python实现CH340串口通信(超详细)
mac python实现CH340串口通信 串口通信介绍 烧录程序 代码实现串口通信 https://www.lanqiao.cn/courses/2947,提供准备好的云主机ros环境,进行实操,课 ...
最新文章
- nginx产生【413 request entity too large】错误的原因与解决方法
- OCR磁盘的导出和导入、备份和恢复以及移动(ocrconfig命令的应用)
- HTML5+Bootstrap 学习笔记 1
- Oracle 创建函数的权限
- r语言随机森林回归预测_从零实现回归随机森林
- error40;无法打开到SQL Server的连接,设置了Tcp/IP等也不能连接的问题
- oopc——5.多态
- 业余学习python有用吗_对于那些不做编程工作的小伙伴来说,学习Python有什么用呢?...
- php 谷歌搜索排名,我想在php中搜索谷歌搜索结果
- Hadoop学习笔记—6.Hadoop Eclipse插件的使用
- 干货分享 | 最新机器学习视频教程与数据集下载(持续更新......)
- Qt Quick 4小时入门-安晓辉-专题视频课程
- 10nm 以一敌二 — 雷蛇灵刃潜行 2020 水银版评测
- CVE(2017-15715、2021-41773、2021-40438)漏洞复现
- 最新Ubuntu20.04安装指南(防踩坑版)
- 怎样识别图片中的文字?手机电脑都可以的
- 用excel进行设计(91):Excel表格的视觉设计技巧
- 如何人声提取音频?手把手教你提取
- 五十一个经典小故事1
- 面试官:vue的这些原理你了解吗?
热门文章
- 设置居中_微信设置个性签名居中,超简单!
- php代码注释处理类库,php代码注释
- ebpf 学习-bpftrace 语法 入门
- android litehttp jar,灵活而智能的HTTP框架 LiteHttp
- python 描述器_python 描述器
- c语言哈希表电子辞典_关于redis涉及的知识点,C语言如何操作redis
- JavaScript面向对象及原型 及setTimeout
- Java代码实现执行Linux服务器命令
- java的同步关键字_简单了解Java synchronized关键字同步
- camel_Apache Camel 2.14中的更多指标