1.协程(单线程实现并发)
2.I/0模型
2.1阻塞I/O
2.2非阻塞I/O

知识点一:协程
协程的目的:是想要在单线程下实现并发(并发看起来是同时运行的)
并发=多个任务间切换+保存状态(正常情况都是由操作系统来控制的)

一般情况下都是由操作系统来控制的,现在要实现的就是遇到I/o自己来切换,也叫并发

优点:在应用程序级别速度要远远高于操作系统的切换
缺点:多个任务一旦有一个阻塞没有切,整个线程都会阻塞原地,该线程内的其他任务
都不能执行

一旦引入协程,就需要检测单线程下所有的IO行为,实际遇到IO就切换,
少一个都不行,一旦一个任务阻塞了,整个线程就阻塞了,其他的任务即便是
可以计算,但是也无法运行了

一个程序没有遇到IO也切,反而会降低效率,应该找到一种让程序遇到IO切,才能提高效率

gevent模块:模拟识别IO阻塞
#gevent模块:模拟识别IO阻塞
import gevent
from gevent import monkey,spawn;monkey.patch_all() #pathch_all()打补丁就是让gevent能识别所有的IO
from threading import current_thread
import time def eat():
print('%s eat 1'%current_thread().name)
# gevent.sleep(2) #默认只能识别自己模块的Io行为
time.sleep(3)
print('%s eat 2'%current_thread().name) def play():
print('%s play 1'%current_thread().name)
# gevent.sleep(1)
time.sleep(1)
print('%s play 2'%current_thread().name) #创建协程对象
g1=spawn(eat,) #spawn(函数名,参数1...) 都是传给函数eat的
g2=spawn(play,) print(current_thread().name)
g1.join() #等待g1结束
g2.join() #等待g2结束 '''输出结果:
MainThread
DummyThread-1 eat 1 #假线程
DummyThread-2 play 1
DummyThread-2 play 2
DummyThread-1 eat 2 ''' '''
而time.sleep(2)或其他的阻塞,gevent是不能直接识别的需要用下面一行代码,打补丁,就可以识别了 from gevent import monkey;monkey.patch_all()必须放到被打补丁者的前面,如time,socket模块之前 或者我们干脆记忆成:要用gevent,需要将from gevent import monkey;monkey.patch_all()放到文件的开头

gevent应用实例一:利用gevent模块改写socket服务端实现:单线程IO切换自动切换

#服务端
from gevent import spawn,monkey;monkey.patch_all()
from socket import *
from threading import Thread def talk(conn):
while True:
try:
data=conn.recv(1024)
if len(data) == 0:break
conn.send(data.upper())
except ConnectionResetError:
break
conn.close() def server(ip,port,backlog=5):
server = socket(AF_INET, SOCK_STREAM)
server.bind((ip, port))
server.listen(backlog) print('starting...')
while True:
conn, addr = server.accept()
spawn(talk,conn) #原来造线程的方式:
# t = Thread(target=talk, args=(conn,))
# t.start() if __name__ == '__main__':
# server('127.0.0.1',8080)
g=spawn(server,'127.0.0.1',8080)
g.join() -------------------------------------------------------------------------------
#客户端
from socket import *
import os client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080)) while True:
msg='%s say hello' %os.getpid()
client.send(msg.encode('utf-8'))
data=client.recv(1024)
print(data.decode('utf-8'))

知识点二:基于网络的IO模型
可以分为2大类:
第一类:
server.accept()
第二类:
conn.recv()
conn.send()

1.recv(收消息)
wait data:等待客户端产生数据--》客户端OS--》网络--》服务端操作系统缓存
copy data:由本地操作系统缓存中的数据拷贝到应用程序的内存中

2.send(发消息)
copy data

阻塞IO:blocking IO
blocking IO就是在执行的2个阶段(等待数据和拷贝数据两个阶段)都被block了

非阻塞IO:non-blocking IO:
思考:目的就是将将recv()阻塞的这个模型变为非阻塞,
即如果没有数据先执行其它的任务,并且最好在没有数据时客户端能返回一个
没有数据的提示信息

非阻塞IO:的问题
1.CPU占用率高(多数的询问是无用的)
2.for循环列表多的情况下会慢
3.数据得不到及时的处理(因为有时候存在可能刚切换到其他任务,数据就过来了
这样就不能及时处理)

非阻塞IO模型改写socket套接字服务端、客户端:

#服务端
from socket import *
import time server = socket(AF_INET, SOCK_STREAM)
server.bind(('127.0.0.1',8080))
server.listen(5)
server.setblocking(False) #所有的IO行为都变为非阻塞模型,设置为False conn_l=[] #保存的是一堆连接,便于后面与每个客户端通信收发消息
while True:
#建立连接循环:
try:
print('总连接数[%s]' % len(conn_l))
conn,addr=server.accept()
conn_l.append(conn)
except BlockingIOError: #客户建立连接请求,报错信息,捕捉这个异常可以执行下面的代码,即执行其他任务
# print('客户端没有数据过来,可以执行其他任务')
del_l=[] #另外新建一个列表单独存放那些非法数据,方便最后清理这些数据 #建立通信循环:
for conn in conn_l:
try:
data=conn.recv(1024) #与accept()建立连接一样,如果没有消息过来,直接
if len(data) == 0: #输入的是空值
del_l.append(conn)
continue
conn.send(data.upper())
except BlockingIOError:
pass
except ConnectionResetError: #客户端单方面终止连接
del_l.append(conn) #将终止的连接添加到定义的列表里面,最后统一删除这些无效的连接 for conn in del_l:
conn_l.remove(conn) -----------------------------------------------------------------------------------------------------------------
#客户端:不需要变动
from socket import *
import os client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080)) while True:
msg='%s say hello' %os.getpid()
client.send(msg.encode('utf-8'))
data=client.recv(1024)
print(data.decode('utf-8'))
 

Python 协程、IO模型的更多相关文章

  1. 协程 & IO模型 & HTTP协议

    今日内容 进程池与线程池的基本使用 协程理论与实操 IO模型 前端简介 内容详细 一.进程池与线程池的基本使用 1.进程池与线程池的作用 为了保证计算机硬件安全的前提下,提升程序的运行效率 2.回调机 ...

  2. 05网络并发 ( GIL+进程池与线程池+协程+IO模型 )

    目录 05 网络并发 05 网络并发

  3. 终结python协程----从yield到actor模型的实现

    把应用程序的代码分为多个代码块,正常情况代码自上而下顺序执行.如果代码块A运行过程中,能够切换执行代码块B,又能够从代码块B再切换回去继续执行代码块A,这就实现了协程 我们知道线程的调度(线程上下文切 ...

  4. day-5 python协程与I/O编程深入浅出

    基于python编程语言环境,重新学习了一遍操作系统IO编程基本知识,同时也学习了什么是协程,通过实际编程,了解进程+协程的优势. 一.python协程编程实现 1.  什么是协程(以下内容来自维基百 ...

  5. 协程IO多路复用

    协程:单线程下实现并发并发:伪并行,遇到IO就切换,单核下多个任务之间切换执行,给你的效果就是貌似你的几个程序在同时执行.提高效率任务切换 + 保存状态并行:多核cpu,真正的同时执行串行:一个任务执 ...

  6. [转载] Python协程从零开始到放弃

    Python协程从零开始到放弃 Web安全 作者:美丽联合安全MLSRC   2017-10-09  3,973   Author: lightless@Meili-inc Date: 2017100 ...

  7. python协程详解

    目录 python协程详解 一.什么是协程 二.了解协程的过程 1.yield工作原理 2.预激协程的装饰器 3.终止协程和异常处理 4.让协程返回值 5.yield from的使用 6.yield ...

  8. Python协程与Go协程的区别二

    写在前面 世界是复杂的,每一种思想都是为了解决某些现实问题而简化成的模型,想解决就得先面对,面对就需要选择角度,角度决定了模型的质量, 喜欢此UP主汤质看本质的哲学科普,其中简洁又不失细节的介绍了人类 ...

  9. python 协程与go协程的区别

    进程.线程和协程 进程的定义: 进程,是计算机中已运行程序的实体.程序本身只是指令.数据及其组织形式的描述,进程才是程序的真正运行实例. 线程的定义: 操作系统能够进行运算调度的最小单位.它被包含在进 ...

  10. Python核心技术与实战——十六|Python协程

    我们在上一章将生成器的时候最后写了,在Python2中生成器还扮演了一个重要的角色——实现Python的协程.那什么是协程呢? 协程 协程是实现并发编程的一种方式.提到并发,肯很多人都会想到多线程/多 ...

随机推荐

  1. java校验maven下载的jar文件

    有时候maven真的很坑! 有时候提示invalid LOC header (bad signat signature), 但又有时候什么都不提示,工程报错,情况有肯多中,不知道大家遇到过几种诡异的. ...

  2. Web端 年月日下拉表 密码判断 按钮判断是否提交

    生日: <asp:DropDownList ID="selYear" runat="server"></asp:DropDownList> ...

  3. 协议学习之 vamei博客系列 总结

    1. 分层: 物理层(physical layer) 所谓的物理层,是指光纤.电缆或者电磁波等真实存在的物理媒介.这些媒介可以传送物理信号,比如亮度.电压或者振幅.对于数字应用来说,我们只需要两种物理 ...

  4. Python静态方法 类方法

    通常情况下,类中函数中定义的所有函数,,都是对象的绑定方法,除此之外,还有专门的静态方法和类方法,这两个是专门给类使用的,但是对象非要调用也是不会报错的. 对象在调用的时候会把自己传递给self,也就 ...

  5. TDB文件介绍

    samba在运行时,Samba 存储许多信息,从本地密码到希望从中收到信息的一系列客户端.这类数据其中一些是暂时的,在 Samba 重启时可能会被丢弃,但是另一些却是永久的,不会被丢弃.这类数据可能是 ...

  6. SQLServer锁原理和锁的类型

    1.锁的用途 为了避免同时争夺数据库资源,将数据库加锁,只有拿到钥匙的用户才能使用: 2.锁的粒度 行锁(Row)--->页锁(Page)--->区锁(Partition 8个页)---- ...

  7. 配置淘宝镜像,不使用怪异的cnpm

    npm config set registry https://registry.npm.taobao.org --global npm config set disturl https://npm. ...

  8. 标准C++(4)继承

    一.继承的作用 若A类继承了B类,可以使A类获得B类中的部分成员变量和成员函数,这能使程序员在已有类的基础上重新定义新的类.继承是类的重要特性,当A类继承了B类,我们称A类为派生类或子类,B类为基类或 ...

  9. 【Shiro】调用doGetAuthenticationInfo进行认证成功之后,isAuthenticated是false的问题。

    使用@Configuration配置shiro无状态登录时出现的问题,在subject.login之后当前线程重新绑定了一个假定subject,isAuthenticated. 这里自定义的访问拦截器 ...

  10. 图解一致性协议2PC和3PC

    原图地址:https://www.processon.com/diagraming/5b89f6ace4b0d4d65bf10786