python事件触发机制-凯发k8官方网
事件驱动模型
传统编程线性模型
开始 ----> 代码块a ---->代码块b ---->代码块c 。。。。。。 结束
每个代码块都有各自实现的功能,按照条件语句顺序判断执行,每一次运行顺序或许都不同,它的控制流程是由获取的数据所和判断语句所决定的。
事件驱动程序模型
开始 ----> 初始化 ----> 等待
事件驱动器启动后,在等待事件触发,然后做出相应的程序执行效果。触发事件包括:输入信息、鼠标、敲击键盘、内部定时器等
io模型
synchronous 同步io
一个进程在执行某个任务时,另外一个进程必须等待其执行完毕,才能继续执行
所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不会返回。按照这个定义,
其实绝大多数函数都是同步调用。但是一般而言,我们在说同步、异步的时候,
特指那些需要其他部件协作或者需要一定时间完成的任务。
asynchronous 异步io
当一个异步功能调用发出后,调用者不能立刻得到结果
当该异步功能完成后,通过状态、通知或回调来通知调用者。如果异步功能用状态来通知,
那么调用者就需要每隔一定时间检查一次,效率就很低(有些初学多线程编程的人,总喜欢用一个循环去检查某个变量的值,这其实是一 种很严重的错误)。
如果是使用通知的方式,效率则很高,因为异步功能几乎不需要做额外的操作。至于回调函数,其实和通知没太多区别。
blocking 阻塞io
调用结果返回之前,当前线程会被挂起
函数只有在得到结果之后才会
将阻塞的线程激活。有人也许会把阻塞调用和同步调用等同起来,实际上他是不同的。对于同步调用来说很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回而已。
non-blocking 非阻塞io
和阻塞io对立
在不能立刻得到结果之前也会立刻返回,同时该函数不会阻塞当前线程
触发方式
水平触发
只有高电平(1)或低电平(0)的时候才触发通知,只要在这两种状态就能得到通知,只要有数据可读,那么水平触发的epoll就立即返回
边缘触发
只有电平发生变化(高电平到低电平,或者低电平到高电平)的时候才触发通知,有数据可读,但没有新的io活动到来,epoll不会立即返回
multiplexing io多路复用
select优缺点对比
select:轮询方式,遍历每个监听对象是否有数据变动,效率较低
epoll:主动响应,主动提交数据变动提升效率
select模块水平触发实现并发io多路复用
服务端
# -*- coding:utf8 -*-
import socket,select
test = socket.socket(socket.af_inet,socket.sock_stream)
#定义socket通信方式和通信协议。socket.af_inet基于网络通信,socket.sock_stream基于tcp协议
test.bind(('127.0.0.1',8000)) # 定义通信id
test.listen(5) # 定义最大通信监听数
inputs = [test,] #定义监听socket对象的列表
while true:
r,w,e = select.select(inputs,[],[],5) # select监听 socket 对象,后跟时间单位为秒
for obj in r: # 遍历监听对象列表
if obj == test: # 判断监听对象是否和上次遍历一样
conn,addr = obj.accept() # 被动接收套接字建立的连接
print('accepted',conn,'from',addr)
inputs.append(conn) # 添加新socket对象到列表
else:
msg = obj.recv(1024) # 定义接收字节信息
print('客户端发送的消息是:', msg)
obj.send(msg.upper()) # 定义发送消息
print("服务监听中...")
服务监听中...
客户端发送的消息是: b'abc'
服务监听中...
客户端发送的消息是: b'aaa'
服务监听中...
客户端
# -*- coding:utf8 -*-
import socket
test = socket.socket(socket.af_inet,socket.sock_stream)
#定义socket通信方式和通信协议。socket.af_inet基于网络通信,socket.sock_stream基于tcp协议
test.connect(('127.0.0.1',8000)) #定义通信id,服务器的地址和端口
while true:
inp = input(">>>").strip() #用户输入发送内容
test.sendall(inp.encode('utf-8')) #定义发送内容
data = test.recv(1024) #定义接收字节信息
print('收到服务端的发来的消息是:',data)
>>>abc
收到服务端的发来的消息是: b'abc'
>>>aaa
收到服务端的发来的消息是: b'aaa'
>>>
selectors模块实现并发io多路复用
服务端
#-*- coding:utf-8 -*-
import selectors,socket
sel = selectors.defaultselector() # 操作系统自识别合适的io多路复用方式
def accept(sock,mask):
conn,addr = sock.accept() # 被动接收套接字建立的连接
conn.setblocking(false) # 设置非阻塞
sel.register(conn,selectors.event_read,read) # conn 和 read 绑定,socket对象有活动调用accept方法
def read(conn,mask):
try: # 异常代码检测防止某个客户端断开连接导致服务终止
data = conn.recv(1024) # 接收数据
if not data: # 判断是否接收到数据
raise exception
conn.send(data.upper()) # 接收到数据并返回数据
except exception as e: # 万能异常
sel.unregister(conn) # 没有接收到数据,解除conn绑定的函数
conn.close() # 关闭连接
sock = socket.socket() # 创建socket对象
sock.bind(('127.0.0.1',8000)) # 定义通信id绑定对象
sock.listen(100) # 定义最大通信监听数
sock.setblocking(false) # 设置非阻塞
sel.register(sock,selectors.event_read,accept) # socket 和 accept 绑定,socket对象有活动调用accept方法
print("服务运行中....")
while true:
events = sel.select() # 监听socket对象
for key,mask in events: # 遍历events对象列表
callback = key.data # 触发socket绑定的函数accept
callback(key.fileobj,mask) # 监听到的有相应的socket对象
服务运行中....
客户端
# -*- coding:utf8 -*-
import socket
test = socket.socket(socket.af_inet,socket.sock_stream)
#定义socket通信方式和通信协议。socket.af_inet基于网络通信,socket.sock_stream基于tcp协议
test.connect(('127.0.0.1',8000)) #定义通信id,服务器的地址和端口
while true:
inp = input(">>>").strip() #用户输入发送内容
test.sendall(inp.encode('utf-8')) #定义发送内容
data = test.recv(1024) #定义接收字节信息
print('收到服务端的发来的消息是:',data)
>>>abc
收到服务端的发来的消息是: b'abc'
>>>
与50位技术专家面对面20年技术见证,附赠技术全景图总结
以上是凯发k8官方网为你收集整理的python事件触发机制_python3-事件驱动、io模型和触发方式的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇:
- 下一篇: