扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
当使用多个线程操作任务的时候,如果线程间有需要通信的地方,那么不可避免的要实现到线程间的通信,来互相通知消息,同步任务的执行。
成都创新互联是专业的颍东网站建设公司,颍东接单;提供成都网站建设、网站制作,网页设计,网站设计,建网站,PHP网站建设等专业做网站服务;采用PHP框架,可快速的进行颍东网站开发网页制作和功能扩展;专业做搜索引擎喜爱的网站,专业的做网站团队,希望更多企业前来合作!
1.线程threading共享内存地址,进程与进程Peocess之间相互独立,互不影响(相当于深拷贝);
2.在线程间通信的时候可以使用Queue模块完成,进程间通信也可以通过Queue完成,但是此Queue并非线程的Queue,进程间通信Queue是将数据 pickle 后传给另一个进程的 Queue,用于父进程与子进程之间的通信或同一父进程的子进程之间通信;
queue
python中的queue模块其实是对数据结构中栈和队列这种数据结构的封装,把抽象的数据结构封装成类的属性和方法
1 2 3 4 5 | #导入线程相关模块 importthreading importqueue
q=queue.Queue() |
1 2 3 4 5 | # 导入进程相关模块 frommultiprocessingimportProcess frommultiprocessingimportQueue
q=Queue() |
1 2 3 4 5 | # 导入进程相关模块 frommultiprocessingimportProcess frommultiprocessingimportPipe
pipe=Pipe() |
python提供了多种进程通信的方式,主要Queue和Pipe这两种方式,Queue用于多个进程间实现通信,Pipe用于两个进程的通信;
put():以插入数据到队列中,他还有两个可选参数:blocked和timeout。详情自行百度
get():从队列读取并且删除一个元素。同样,他还有两个可选参数:blocked和timeout。详情自行百度
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | # !usr/bin/env python # -*- coding:utf-8 _*- """ @Author:何以解忧 @Blog(个人博客地址): shuopython.com @WeChat Official Account(微信公众号):猿说python @Github:www.github.com
@File:python_process_queue.py @Time:2019/12/21 21:25
@Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累! """
frommultiprocessingimportProcess frommultiprocessingimportQueue importos,time,random
#写数据进程执行的代码 defproc_write(q,urls): print('Process is write....') forurlinurls: q.put(url) print('put %s to queue... '%url) time.sleep(random.random())
#读数据进程的代码 defproc_read(q): print('Process is reading...') whileTrue: url=q.get(True) print('Get %s from queue'%url)
if__name__=='__main__': #父进程创建Queue,并传给各个子进程 q=Queue() proc_write1=Process(target=proc_write,args=(q,['url_1','url_2','url_3'])) proc_write2=Process(target=proc_write,args=(q,['url_4','url_5','url_6'])) proc_reader=Process(target=proc_read,args=(q,)) #启动子进程,写入 proc_write1.start() proc_write2.start()
proc_reader.start() #等待proc_write1结束 proc_write1.join() proc_write2.join() #proc_raader进程是死循环,强制结束 proc_reader.terminate() print("mian") |
输出结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | Processiswrite.... puturl_1toqueue... Processiswrite.... puturl_4toqueue... Processisreading... Geturl_1fromqueue Geturl_4fromqueue puturl_5toqueue... Geturl_5fromqueue puturl_2toqueue... Geturl_2fromqueue puturl_3toqueue... Geturl_3fromqueue puturl_6toqueue... Geturl_6fromqueue mian |
Pipe常用于两个进程,两个进程分别位于管道的两端 * Pipe方法返回(conn1,conn2)代表一个管道的两个端,Pipe方法有duplex参数,默认为True,即全双工模式,若为FALSE,conn1只负责接收信息,conn2负责发送,Pipe同样也包含两个方法:
send() : 发送信息;
recv() : 接收信息;
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 26 27 28 29 30 | frommultiprocessingimportProcess frommultiprocessingimportPipe importos,time,random #写数据进程执行的代码 defproc_send(pipe,urls): #print 'Process is write....' forurlinurls:
print('Process is send :%s'%url) pipe.send(url) time.sleep(random.random())
#读数据进程的代码 defproc_recv(pipe): whileTrue: print('Process rev:%s'%pipe.recv()) time.sleep(random.random())
if__name__=='__main__': #父进程创建pipe,并传给各个子进程 pipe=Pipe() p1=Process(target=proc_send,args=(pipe[0],['url_'+str(i)foriinrange(10)])) p2=Process(target=proc_recv,args=(pipe[1],)) #启动子进程,写入 p1.start() p2.start()
p1.join() p2.terminate() print("mian") |
输出结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | Processissend:url_0 Processrev:url_0 Processissend:url_1 Processrev:url_1 Processissend:url_2 Processrev:url_2 Processissend:url_3 Processrev:url_3 Processissend:url_4 Processrev:url_4 Processissend:url_5 Processissend:url_6 Processissend:url_7 Processrev:url_5 Processissend:url_8 Processissend:url_9 Processrev:url_6 mian |
当然我们也可以尝试使用线程threading的Queue是否能完成线程间通信,示例代码如下:
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 | frommultiprocessingimportProcess # from multiprocessing import Queue # 进程间通信Queue,两者不要混淆 importqueue # 线程间通信queue.Queue,两者不要混淆 importtime
defp_put(q,*args): q.put(args) print('Has put %s'%args)
defp_get(q,*args): print('%s wait to get...'%args)
print(q.get()) print('%s got it'%args)
if__name__=="__main__": q=queue.Queue() p1=Process(target=p_put,args=(q,'p1',)) p2=Process(target=p_get,args=(q,'p2',)) p1.start() p2.start() |
直接异常报错:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Traceback(mostrecentcalllast): File"E:/Project/python_project/untitled10/123.py",line38,in p1.start() File"G:\ProgramData\Anaconda3\lib\multiprocessing\process.py",line105,instart self._popen=self._Popen(self) File"G:\ProgramData\Anaconda3\lib\multiprocessing\context.py",line223,in_Popen return_default_context.get_context().Process._Popen(process_obj) File"G:\ProgramData\Anaconda3\lib\multiprocessing\context.py",line322,in_Popen returnPopen(process_obj) File"G:\ProgramData\Anaconda3\lib\multiprocessing\popen_spawn_win32.py",line65,in__init__ reduction.dump(process_obj,to_child) File"G:\ProgramData\Anaconda3\lib\multiprocessing\reduction.py",line60,indump ForkingPickler(file,protocol).dump(obj) TypeError:can'tpickle_thread.lockobjects |
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流