python事件触发机制_Python3-事件驱动、IO模型和触发方式
事件驅動模型
傳統編程線性模型
開始 ----> 代碼塊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年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的python事件触发机制_Python3-事件驱动、IO模型和触发方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python脚本迁移数据库_Python
- 下一篇: python图形设置_python学习笔