selectors 模块
它的功能与 linux 的 epoll,还是 select 模块, poll 等类似;
实现高效的 I/O multiplexing , 常用于非阻塞的 socket 的编程中
官方文档
内部类
? BaseSelector
? SelectSelector
? PollSelector
? EpollSelector
? DevpollSelector
? KqueueSelector
? DefaultSelector
实际使用为此类, 自动选择为当前环境中最有效的 Selector ,
所以平时用 DefaultSelector 类就可以了,其它用不着
定义事件类型
? EVENT_READ - 表示可读
? EVENT_WRITE - 表示可写
SelectorKey类
模块定义了一个 SelectorKey 类, 一般用这个类的实例 来描述一个已经注册的文件对象的状态, 这个类的几个属性常用到:
? fileobj - 表示已经注册的文件对象;
? fd - 表示文件对象的描述符,是一个整数,它是文件对象的 fileno() 方法的返回值;
? events - 表示注册一个文件对象时,我们等待的 events , 即上面的 event Mask , 是可读呢还是可写呢!!
? data - 表示注册一个文件对象是邦定的 data ;
常用方法
register(fileobj, events, data=None)
作用
注册一个文件对象。
参数
fileobj 即可以是fd 也可以是一个拥有 fileno() 方法的对象;
events上面的 event Mask 常量 data
返回值
一个 SelectorKey 类的实例
unregister(fileobj)
作用
注销一个已经注册过的文件对象;
返回值
一个 SelectorKey 类的实例
modify(fileobj, events, data=None)
作用
用于修改一个注册过的文件对象,比如从监听可读变为监听可写
它其实就是 register() 后再跟 unregister()
但是使用 modify() 更高效
返回值
一个 SelectorKey 类的实例
select(timeout=None)
作用
用于选择满足我们监听的 event 的文件对象
返回值
是一个 (key, events) 的元组,
其中 key 是一个 SelectorKey 类的实例,
而 events 就是 event Mask ( EVENT_READ 或 EVENT_WRITE ,或者二者的组合)
close()
作用
关闭 selector
最后一定要记得调用它, 要确保所有的资源被释放;
get_key(fileobj)
作用
返回注册文件对象的 key ;
返回值
一个 SelectorKey 类的实例;
实例
官方实例
import selectors import socket sel = selectors.DefaultSelector() def accept(sock, mask): conn, addr = sock.accept() # Should be ready print(‘accepted‘, conn, ‘from‘, addr) conn.setblocking(False) sel.register(conn, selectors.EVENT_READ, read) def read(conn, mask): data = conn.recv(1000) # Should be ready if data: 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‘, 1234)) sock.listen(100) sock.setblocking(False) sel.register(sock, selectors.EVENT_READ, accept) while True: events = sel.select() for key, mask in events: callback = key.data callback(key.fileobj, mask)
易懂实例
#!/usr/bin/python import selectors import socket # selectors模块默认会用epoll,如果你的系统中没有epoll(比如windows)则会自动使用select sel = selectors.DefaultSelector() # 生成一个select对象 def accept(sock, mask): conn, addr = sock.accept() # Should be ready print(‘accepted‘, conn, ‘from‘, addr) conn.setblocking(False) # 设定非阻塞 sel.register(conn, selectors.EVENT_READ, read) # 新连接注册read回调函数 def read(conn, mask): data = conn.recv(1024) # Should be ready if data: print(‘echoing‘, repr(data), ‘to‘, conn) conn.send(data) else: print(‘closing‘, conn) sel.unregister(conn) conn.close() sock = socket.socket() sock.bind((‘localhost‘, 8080)) sock.listen() sock.setblocking(False) sel.register(sock, selectors.EVENT_READ, accept) # 把刚生成的sock连接对象注册到select连接列表中,并交给accept函数处理 while True: events = sel.select() # 默认是阻塞,有活动连接就返回活动的连接列表 # 这里看起来是select,其实有可能会使用epoll,如果你的系统支持epoll,那么默认就是epoll for key, mask in events: callback = key.data # 去调accept函数 callback(key.fileobj, mask) # key.fileobj就是readable中的一个socket连接对象
原文地址:https://www.cnblogs.com/shijieli/p/10875663.html