python中的select模塊有什么用-創(chuàng)新互聯(lián)

創(chuàng)新互聯(lián)www.cdcxhl.cn八線動(dòng)態(tài)BGP香港云服務(wù)器提供商,新人活動(dòng)買多久送多久,劃算不套路!

創(chuàng)新互聯(lián)主打移動(dòng)網(wǎng)站、成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)、網(wǎng)站改版、網(wǎng)絡(luò)推廣、網(wǎng)站維護(hù)、主機(jī)域名、等互聯(lián)網(wǎng)信息服務(wù),為各行業(yè)提供服務(wù)。在技術(shù)實(shí)力的保障下,我們?yōu)榭蛻舫兄Z穩(wěn)定,放心的服務(wù),根據(jù)網(wǎng)站的內(nèi)容與功能再?zèng)Q定采用什么樣的設(shè)計(jì)。最后,要實(shí)現(xiàn)符合網(wǎng)站需求的內(nèi)容、功能與設(shè)計(jì),我們還會(huì)規(guī)劃穩(wěn)定安全的技術(shù)方案做保障。

這篇文章運(yùn)用簡單易懂的例子給大家介紹python中的select模塊有什么用,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。

簡介

Python中的select模塊專注于I/O多路復(fù)用,提供了select  poll  epoll三個(gè)方法(其中后兩個(gè)在Linux中可用,windows僅支持select),另外也提供了kqueue方法(freeBSD系統(tǒng))

select方法

進(jìn)程指定內(nèi)核監(jiān)聽哪些文件描述符(最多監(jiān)聽1024個(gè)fd)的哪些事件,當(dāng)沒有文件描述符事件發(fā)生時(shí),進(jìn)程被阻塞;當(dāng)一個(gè)或者多個(gè)文件描述符事件發(fā)生時(shí),進(jìn)程被喚醒。

當(dāng)我們調(diào)用select()時(shí):

1、上下文切換轉(zhuǎn)換為內(nèi)核態(tài)

2、將fd從用戶空間復(fù)制到內(nèi)核空間

3、內(nèi)核遍歷所有fd,查看其對(duì)應(yīng)事件是否發(fā)生

4、如果沒發(fā)生,將進(jìn)程阻塞,當(dāng)設(shè)備驅(qū)動(dòng)產(chǎn)生中斷或者timeout時(shí)間后,將進(jìn)程喚醒,再次進(jìn)行遍歷

5、返回遍歷后的fd

6、將fd從內(nèi)核空間復(fù)制到用戶空間

fd:file descriptor 文件描述符

fd_r_list, fd_w_list, fd_e_list = select.select(rlist, wlist, xlist, [timeout])

參數(shù): 可接受四個(gè)參數(shù)(前三個(gè)必須)

rlist: wait until ready for reading
wlist: wait until ready for writing
xlist: wait for an “exceptional condition”
timeout: 超時(shí)時(shí)間

返回值:三個(gè)列表

select方法用來監(jiān)視文件描述符(當(dāng)文件描述符條件不滿足時(shí),select會(huì)阻塞),當(dāng)某個(gè)文件描述符狀態(tài)改變后,會(huì)返回三個(gè)列表

1、當(dāng)參數(shù)1 序列中的fd滿足“可讀”條件時(shí),則獲取發(fā)生變化的fd并添加到fd_r_list中

2、當(dāng)參數(shù)2 序列中含有fd時(shí),則將該序列中所有的fd添加到 fd_w_list中

3、當(dāng)參數(shù)3 序列中的fd發(fā)生錯(cuò)誤時(shí),則將該發(fā)生錯(cuò)誤的fd添加到 fd_e_list中

4、當(dāng)超時(shí)時(shí)間為空,則select會(huì)一直阻塞,直到監(jiān)聽的句柄發(fā)生變化

當(dāng)超時(shí)時(shí)間 = n(正整數(shù))時(shí),那么如果監(jiān)聽的句柄均無任何變化,則select會(huì)阻塞n秒,之后返回三個(gè)空列表,如果監(jiān)聽的句柄有變化,則直接執(zhí)行。

實(shí)例

利用select實(shí)現(xiàn)一個(gè)可并發(fā)的服務(wù)

import socket
import select
  
s = socket.socket()
s.bind(('127.0.0.1',8888))
s.listen(5)
r_list = [s,]
num = 0
while True:
 rl, wl, error = select.select(r_list,[],[],10)
 num+=1
 print('counts is %s'%num)
 print("rl's length is %s"%len(rl))
 for fd in rl:
  if fd == s:
   conn, addr = fd.accept()
   r_list.append(conn)
   msg = conn.recv(200)
   conn.sendall(('first----%s'%conn.fileno()).encode())
  else:
   try:
    msg = fd.recv(200)
    fd.sendall('second'.encode())
   except ConnectionAbortedError:
    r_list.remove(fd)
  
s.close()
import socket
  
flag = 1
s = socket.socket()
s.connect(('127.0.0.1',8888))
while flag:
 input_msg = input('input>>>')
 if input_msg == '0':
  break
 s.sendall(input_msg.encode())
 msg = s.recv(1024)
 print(msg.decode())
  
s.close()

epoll方法:

epoll很好的改進(jìn)了select:

1、epoll的解決方案在epoll_ctl函數(shù)中。每次注冊(cè)新的事件到epoll句柄中時(shí),會(huì)把所有的fd拷貝進(jìn)內(nèi)核,而不是在epoll_wait的時(shí)候重復(fù)拷貝。epoll保證了每個(gè)fd在整個(gè)過程中只會(huì)拷貝一次。

2、epoll會(huì)在epoll_ctl時(shí)把指定的fd遍歷一遍(這一遍必不可少)并為每個(gè)fd指定一個(gè)回調(diào)函數(shù),當(dāng)設(shè)備就緒,喚醒等待隊(duì)列上的等待者時(shí),就會(huì)調(diào)用這個(gè)回調(diào)函數(shù),而這個(gè)回調(diào)函數(shù)會(huì)把就緒的fd加入一個(gè)就緒鏈表。epoll_wait的工作實(shí)際上就是在這個(gè)就緒鏈表中查看有沒有就緒的fd

3、epoll對(duì)文件描述符沒有額外限制

select.epoll(sizehint=-1, flags=0) 創(chuàng)建epoll對(duì)象
epoll.close()
Close the control file descriptor of the epoll object.關(guān)閉epoll對(duì)象的文件描述符
epoll.closed
True if the epoll object is closed.檢測epoll對(duì)象是否關(guān)閉
epoll.fileno()
Return the file descriptor number of the control fd.返回epoll對(duì)象的文件描述符
epoll.fromfd(fd)
Create an epoll object from a given file descriptor.根據(jù)指定的fd創(chuàng)建epoll對(duì)象
epoll.register(fd[, eventmask])
Register a fd descriptor with the epoll object.向epoll對(duì)象中注冊(cè)fd和對(duì)應(yīng)的事件
epoll.modify(fd, eventmask)
Modify a registered file descriptor.修改fd的事件
epoll.unregister(fd)
Remove a registered file descriptor from the epoll object.取消注冊(cè)
epoll.poll(timeout=-1, maxevents=-1)
Wait for events. timeout in seconds (float)阻塞,直到注冊(cè)的fd事件發(fā)生,會(huì)返回一個(gè)dict,格式為:{(fd1,event1),
(fd2,event2),……(fdn,eventn)}

epoll實(shí)例:

import socket
import select
  
s = socket.socket()
s.bind(('127.0.0.1',8888))
s.listen(5)
epoll_obj = select.epoll()
epoll_obj.register(s,select.EPOLLIN)
connections = {}
while True:
 events = epoll_obj.poll()
 for fd, event in events:
  print(fd,event)
  if fd == s.fileno():
   conn, addr = s.accept()
   connections[conn.fileno()] = conn
   epoll_obj.register(conn,select.EPOLLIN)
   msg = conn.recv(200)
   conn.sendall('ok'.encode())
  else:
   try:
    fd_obj = connections[fd]
    msg = fd_obj.recv(200)
    fd_obj.sendall('ok'.encode())
   except BrokenPipeError:
    epoll_obj.unregister(fd)
    connections[fd].close()
    del connections[fd]
  
s.close()
epoll_obj.close()
import socket
  
flag = 1
s = socket.socket()
s.connect(('127.0.0.1',8888))
while flag:
 input_msg = input('input>>>')
 if input_msg == '0':
  break
 s.sendall(input_msg.encode())
 msg = s.recv(1024)
 print(msg.decode())
  
s.close()

關(guān)于python中的select模塊有什么用就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

當(dāng)前文章:python中的select模塊有什么用-創(chuàng)新互聯(lián)
分享URL:http://muchs.cn/article4/djiooe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站建設(shè)、網(wǎng)站制作App設(shè)計(jì)、全網(wǎng)營銷推廣、虛擬主機(jī)、Google

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都app開發(fā)公司