python异步和进程_12.python进程\协程\异步IO
进程
Python中的多线程无法利用多核优势 , 所以如果我们想要充分地使用多核CPU的资源 , 那么就只能靠多进程了
multiprocessing模块中提供了Process , Queue , Pipe , Lock , RLock , Event , Condition等组件 , 与threading模块有很多相似之处
1.创建进程
from multiprocessing importProcessimporttimedeffunc(name):
time.sleep(2)print('hello',name)if __name__ == '__main__':
p= Process(target=func,args=('derek',))
p.start()#p.join()
print('end...')
View Code
2.进程间通讯
(1)Queue
不同进程间内存是不共享的,要想实现两个进程间的数据交换。进程间通信有两种主要形式 , 队列和管道
from multiprocessing import Process, Queue #Queue是进程排列
deff(test):
test.put('22') #通过创建的子进程往队列添加数据,实线父子进程交互
if __name__ == '__main__':
q= Queue() #父进程
q.put("11")
p= Process(target=f, args=(q,)) #子进程
p.start()
p.join()print("取到:",q.get_nowait())print("取到:",q.get_nowait())#父进程在创建子进程的时候就把q克隆一份给子进程#通过pickle序列化、反序列化,来达到两个进程之间的交互
结果:
取到:11取到:22
Queue
(2)Pipe(管道)
The Pipe() function returns a pair of connection objects connected by a pipe which by default is duplex (two-way).
from multiprocessing importProcess, Pipedeff(conn):
conn.send('11')
conn.send('22')print("from parent:",conn.recv())print("from parent:", conn.recv())
conn.close()if __name__ == '__main__':
parent_conn, child_conn= Pipe() #生成管道实例,可以互相send()和recv()
p= Process(target=f, args=(child_conn,))
p.start()print(parent_conn.recv()) #prints "11"
print(parent_conn.recv()) #prints "22"
parent_conn.send("33") #parent 发消息给 child
parent_conn.send("44")
p.join()
Pipe
3.Manager
进程之间是相互独立的 ,Queue和pipe只是实现了数据交互,并没实现数据共享,Manager可以实现进程间数据共享 。
Manager还支持进程中的很多操作 , 比如Condition , Lock , Namespace , Queue , RLock , Semaphore等
from multiprocessing importProcess, Managerimportosdeff(d, l):
d[os.getpid()]=os.getpid()
l.append(os.getpid())print(l)if __name__ == '__main__':
with Manager() as manager:
d= manager.dict() #{} #生成一个字典,可在多个进程间共享和传递
l= manager.list(range(5)) #生成一个列表,可在多个进程间共享和传递
p_list =[]for i in range(2):
p= Process(target=f, args=(d, l))
p.start()
p_list.append(p)for res in p_list: #等待结果
res.join()print(d)print(l)
View Code
4.lock
from multiprocessing importProcess, Lockdeff(l, i):#l.acquire()
print('hello world', i)#l.release()
if __name__ == '__main__':
lock=Lock()for num in range(100):
Process(target=f, args=(lock, num)).start() #要把lock传到函数的参数l
#lock防止在屏幕上打印的时候会乱
lock
5.进程池
进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进程,那么程序就会等待,直到进程池中有可用进程为止。
进程池中有以下几个主要方法:
apply:从进程池里取一个进程并执行
apply_async:apply的异步版本
terminate:立刻关闭线程池
join:主进程等待所有子进程执行完毕,必须在close或terminate之后
close:等待所有进程结束后,才关闭线程池
from multiprocessing importProcess, PoolimporttimeimportosdefFoo(i):
time.sleep(2)print("in process",os.getpid())return i + 100
defBar(arg):print('-->exec done:', arg,os.getpid())if __name__ == '__main__': #多进程,必须加这一句(windows系统)
pool = Pool(processes=3) #允许进程池同时放入3个进程
print("主进程",os.getpid())for i in range(10):
pool.apply_async(func=Foo, args=(i,), callback=Bar) #callback=回调,执行完Foo(),接着执行Bar()
#pool.apply(func=Foo, args=(i,)) #串行
print('end')
pool.close()
pool.join()#进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。必须先close(),再join()
Pool
协程
1.简介
协程(Coroutine) : 是单线程下的并发 , 又称微线程 , 纤程 . 协程是一种用户态的轻量级线程 , 即协程有用户自己控制调度
协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。
协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态
使用协程的优缺点
优点 :
协程的切换开销更小 , 属于程序级别的切换 , 更加轻量级
单线程内就可以实现并发的效果 , 最大限度利用CPU
缺点 :
协程的本质是单线程下 , 无法利用多核 , 可以是一个程序开启多个进程 , 每个进程内开启多个线程 , 每个线程内开启协程
协程指的是单个线程 , 因而一旦协程出现阻塞 将会阻塞整个线程
2.Greenlet
greenlet是一个用C实现的协程模块,相比与python自带的yield,它可以使你在任意函数之间随意切换,而不需把这个函数先声明为generator
手动切换
from greenlet importgreenletdeftest1():print(12)
gr2.switch()#到这里切换到gr2,执行test2()
print(34)
gr2.switch()#切换到上次gr2运行的位置
deftest2():print(56)
gr1.switch()#切换到上次gr1运行的位置
print(78)
gr1= greenlet(test1) #启动一个协程gr1
gr2 = greenlet(test2) #启动一个协程gr2
gr1.switch()#开始运行gr1
greenlet
3.Gevent
Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。
(1)IO阻塞自动切换
importgeventdeffoo():print('Running in foo')
gevent.sleep(2)print('阻塞时间最长,最后运行')defbar():print('running in bar')
gevent.sleep(1)print('foo()还在阻塞,这里第二个运行')deffunc3():print("running in func3")
gevent.sleep(0)print("其它两个还在IO阻塞先运行")#创建协程实例
gevent.joinall([
gevent.spawn(foo),#生成,
gevent.spawn(bar),
gevent.spawn(func3),
])#遇到IO自动切换
结果:
Runninginfoo
runninginbar
runninginfunc3
其它两个还在IO阻塞先运行
foo()还在阻塞,这里第二个运行
阻塞时间最长,最后运行
Process finished with exit code 0
View Code
由于切换是在IO操作时自动完成,所以gevent需要修改Python自带的一些标准库,这一过程在启动时通过monkey patch完成:
(2)爬虫例子:
from urllib importrequestimportgevent,timefrom gevent importmonkey
monkey.patch_all()#作用:把当前程序的所有的io操作给我单独的做上标记
deff(url):print('GET: %s' %url)
resp=request.urlopen(url)
data=resp.read()print('%d bytes received from %s.' %(len(data), url))#同步需要的时间
urls = ['https://www.python.org/','https://www.yahoo.com/','https://github.com/']
time_start=time.time()for url inurls:
f(url)print("同步cost",time.time() -time_start)#下面是异步花费的时间
async_time_start =time.time()
gevent.joinall([
gevent.spawn(f,'https://www.python.org/'),
gevent.spawn(f,'https://www.yahoo.com/'),
gevent.spawn(f,'https://github.com/'),
])print("异步cost",time.time() -async_time_start)
结果:
GET: https://www.python.org/
48954 bytes received from https://www.python.org/.
GET: https://www.yahoo.com/
491871 bytes received from https://www.yahoo.com/.
GET: https://github.com/
51595 bytes received from https://github.com/.
同步cost4.928282260894775GET: https://www.python.org/GET: https://www.yahoo.com/GET: https://github.com/
48954 bytes received from https://www.python.org/.494958 bytes received from https://www.yahoo.com/.51599 bytes received from https://github.com/.
异步cost1.4920852184295654
IO多路复用
详解:http://www.cnblogs.com/alex3714/articles/5876749.html
selectors模块
selectors基于select模块实现IO多路复用,调用语句selectors.DefaultSelector(),特点是根据平台自动选择最佳IO多路复用机制,调用顺序:epoll > poll > select
做一个socket servers
importselectorsimportsocket
sel= selectors.DefaultSelector() #根据平台自动选择最佳IO多路复用机制
defaccept(sock, mask):
conn, addr= sock.accept() #Should be ready
#print('accepted', conn, 'from', addr,mask)
conn.setblocking(False) #设置为非阻塞IO
sel.register(conn, selectors.EVENT_READ, read)#新连接注册read回调函数
#将conn和read函数注册到一起,当conn有变化时执行read函数
defread(conn, mask):
data= conn.recv(1024) #Should be ready
ifdata:print('echoing', repr(data), 'to', conn)
conn.send(data)#Hope it won't block
else:print('closing', conn)
sel.unregister(conn)
conn.close()
sock=socket.socket()
sock.bind(('localhost', 9999))
sock.listen(100)
sock.setblocking(False)#设置为非阻塞IO
sel.register(sock, selectors.EVENT_READ, accept)#将sock和accept函数注册到一起,当sock有变化时执行accept函数
whileTrue:
events= sel.select() #默认阻塞,有活动连接就返回活动的连接列表,监听[(key1,mask1),(key2),(mask2)]
for key, mask inevents:
callback= key.data #accept #1 key.data就是accept # 2 key.data就是read
callback(key.fileobj, mask) #key.fileobj= 文件句柄
#1 key.fileobj就是sock # 2 key.fileobj就是conn
server
client
importsocketimportsys
messages= [ b'This is the message.',
b'It will be sent',
b'in parts.',
]
server_address= ('localhost', 9999)#Create a TCP/IP socket
socks = [ socket.socket(socket.AF_INET, socket.SOCK_STREAM) for i in range(5)]print(socks)#Connect the socket to the port where the server is listening
print('connecting to %s port %s' %server_address)for s insocks:
s.connect(server_address)for message inmessages:#Send messages on both sockets
for s insocks:print('%s: sending "%s"' %(s.getsockname(), message) )
s.send(message)#Read responses on both sockets
for s insocks:
data= s.recv(1024)print( '%s: received "%s"' %(s.getsockname(), data) )if notdata:print( 'closing socket', s.getsockname() )
mutlti conn socket client
python异步和进程_12.python进程\协程\异步IO相关推荐
- python(40)- 进程、线程、协程及IO模型
一.操作系统概念 操作系统位于底层硬件与应用软件之间的一层.工作方式:向下管理硬件,向上提供接口. 操作系统进行进程切换:1.出现IO操作:2.固定时间. 固定时间很短,人感受不到.每一个应用层运行起 ...
- python 基础 进程,线程,协程,并发并行,异步同步的定义
进程,线程,协程 进程:是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础. 用大白话说就是系统执行某一项过程的行为,比如你用浏览器在线播放器 ...
- 怎么更进一步学python_【百尺竿头,更进一步学Python】Python进阶课程——进程,线程和协程的区别...
本文带来各类奇怪的IT百科知识. [百尺竿头,更进一步学Python]Python进阶课程--进程:线程和协程的区别 现在多进程多线程已经是老生常谈了:协程也在最近几年流行起来.今天我们本文主要介绍进 ...
- Python进阶(5)_进程与线程之协程、I/O模型
三.协程 3.1协程概念 协程:又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存 ...
- Python 进程、线程、协程傻傻分不清楚?详细总结(附代码)
目录 1 什么是并发编程? 2 进程与多进程 3 线程与多线程 4 协程与多协程 5 总结 1 什么是并发编程? 并发编程是实现多任务协同处理,改善系统性能的方式.Python中实现并发编程主要依靠 ...
- python并发编程-进程池线程池-协程-I/O模型-04
目录 进程池线程池的使用***** 进程池/线程池的创建和提交回调 验证复用池子里的线程或进程 异步回调机制 通过闭包给回调函数添加额外参数(扩展) 协程*** 概念回顾(协程这里再理一下) 如何实现 ...
- python 协程、进程、线程_Python的进程、线程和协程 · Donzy’s Blogs
0.前言 在计算机技术领域,吞吐量(throughput)是计算机在指定的一段时间内完成编程技术如何影响.本文主要讨论Python的多进程.多线程及协程等编程技术在不同场景下对系统吞吐量的影响. 1. ...
- python进程线程协程区别_进程和线程、协程的区别
现在多进程多线程已经是老生常谈了,协程也在最近几年流行起来.python中有协程库gevent,py web框架tornado中也用了gevent封装好的协程.本文主要介绍进程.线程和协程三者之间的区 ...
- python线程协程进程的区别_进程和线程、协程的区别
现在多进程多线程已经是老生常谈了,协程也在最近几年流行起来.python中有协程库gevent,py web框架tornado中也用了gevent封装好的协程.本文主要介绍进程.线程和协程三者之间的区 ...
- python 多线程和协程结合_一文讲透 “进程、线程、协程”
本文从操作系统原理出发结合代码实践讲解了以下内容: 什么是进程,线程和协程? 它们之间的关系是什么? 为什么说Python中的多线程是伪多线程? 不同的应用场景该如何选择技术方案? ... 什么是进程 ...
最新文章
- 逐飞mini车样品说明
- 2.redis配置详解
- java如何画出表格_Java利用iText7画个性化表格
- 消息队列RocketMQ应对双十一流量洪峰的“六大武器”
- 活动运营的核心要点:如何保证拉新用户是有价值的?
- SSH中后台传到前台一个信息集合,tr td中怎么进行排列,类似在一个div里排列书籍...
- PyCharm3.0默认快捷键
- abb软启动器pstx手册_关于 ABB工业机器人碰撞检测功能的介绍
- (小白)函数一: 声明函数的方法—语句定义法和表达式定义法的区别
- 第一次收到这么用心的感谢信
- mongodb 系列 ~ mongo 用户验证系列
- greenplum 外部表 oracle,GREENPLUM使用技巧(一)- 使用外部表实现DBLINK功能
- iOS 使用ZipArchive压缩文件
- 自己闲着没事整理的人工智能思维导图(2(鸢尾花))
- 用shell打印正三角形_用shell命令绘制三角形
- 如何在“运行”里打开软件
- UiPath:以API接口方式启动流程
- 01 网易云音乐 vant -黑
- c语言判断两个字母相等,C语言:比较两个字符串是否相等
- C语言低配版扫雷游戏
热门文章
- 关于windows图形编程 Hello2 程序的问题
- 备份数据库的expdp语句_Oracle中利用expdp/impdp备份数据库的使用说明
- 如何将本地python项目部署到服务器上_如何将本地的Django项目部署到云服务器
- oracle添加文件,ORACLE---添加控制文件
- pip升级python版本_GEE学习笔记 六十八:【GEE之Python版教程二】配置Python开发环境...
- ustc linux 网络通,USTC 网络通脚本
- php学了基本语法后应该怎么做,PHP编程入门的基本语法知识点总结
- easy mysql_GitHub - aleafs/easymysql: mysql client in cluster, based on node-mysql
- 【算法竞赛学习】二手车交易价格预测-Baseline
- CodeForces - 1058A. In Search of an Easy Problem