Python 第三方模块之 APScheduler - 定时任务

https://docs.python.org/zh-cn/3/library/selectors.html

注解:selectors 模块是在 select 模块原型的基础上进行高级且高效的 I/O 复用。推荐用户改用 selectors 模块,除非用户希望对 OS 级的函数原型进行精确控制。

selectors 主要的函数:

selectors.DefaultSelector() 自动选择文件IO模型

选择一个当前平台最优的IO模型,一般来说是 epoll 或 kqueue。存在的可选项包括:

  • SelectSelector
  • PollSelector
  • EpollSelector
  • DevpollSelector
  • KqueueSelector

DefaultSelector 是一个指向当前平台上可用的最高效实现的别名,当选择epoll时,可以认为 sel = EpollSelector。返回:一个select对象

sel.register(sock, selectors.EVENT_READ, accept) 文件注册

函数原型:register(fileobj, events, data=None)

注册一个用于选择的文件对象,在其上监视 I/O 事件。

fileobj 是要监视的文件对象。它可以是整数形式的文件描述符或者具有 fileno() 方法的对象。

events 是要监视的事件的位掩码。

data 是一个任意对象或变量。

返回:这将返回一个新的 SelectorKey 实例,实例具体内容见下一个函数的key

events = sel.select() 获取就绪文件

函数原型:select(timeout=None)

可用于遍历获取状态变为就绪注册的文件,如果设置超时时间则可能会抛出超时异常。返回:一个(key, events)的元组,

  • key: 一个SelectorKey类的实例,包括
  • fileobj: 已注册的文件对象。
  • fd: 下层的文件描述符

events: 必须在此文件对象上被等待的事件。

events:文件句柄可读还是可写的标识。为EVENT_READ或EVENT_WRITE,或者二者的组合

示例

服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import selectors
import socket


# 根据平台自动选择最佳的IO多路机制,比如linux就会选择epoll,windows会选择select
sel = selectors.DefaultSelector()

def accept(sock, mask):
# 建立客户端连接
conn, addr = sock.accept()
print('accepted', conn, 'from', addr)
# 设置非阻塞模式
conn.setblocking(False)
# 再次注册一个连接,将其加入监测列表中,
sel.register(conn, selectors.EVENT_READ, read)

def read(conn, mask):
try: # 抛出客户端强制关闭的异常(如手动关闭客户端黑窗口)
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('Client closed.', conn)
# 将conn从监测列表删除
sel.unregister(conn)
conn.close()
except ConnectionResetError:
print('Client forcibly closed.', conn)
# 将conn从监测列表删除
sel.unregister(conn)
conn.close()

# 创建socket对象
sock = socket.socket()

# 绑定端口,设置监听
sock.bind(('localhost', 1234))
sock.listen(100)

# 设置为非阻塞模式
sock.setblocking(False)

# 注册一个文件对象,监测它的IO事件,data是和文件对象相关的数据(此处放置了一个 accept 函数的内存地址)
# register(fileobj, events, data=None)
sel.register(sock, selectors.EVENT_READ, accept)

while True:
'''
sel.select()
看似是select方法,实际上会根据平台自动选择使用select还是epoll
它返回一个(key, events)元组, key是一个namedtuple类型的元组,可以使用 key.name 获取元组的数据
key 的内容(fileobj,fd,events,data):
fileobj 已经注册的文件对象
fd 也就是第一个参数的那个文件对象的更底层的文件描述符
events 等待的IO事件
data 可选项。可以存一些和fileobj有关的数据,如 sessioin 的 id
'''
events = sel.select() # 监测有无活动对象,没有就阻塞在这里等待
for key, mask in events: # 有活动对象了
callback = key.data # key.data 是注册时传递的 accept 函数
callback(key.fileobj, mask) # key.fileobj 就是传递的 socket 对象

客户端

1
2
3
4
5
6
7
8
9
10
import socket


tin=socket.socket()
tin.connect(('localhost',1234))
while True:
inp=input('>>>>')
tin.send(inp.encode('utf8'))
data=tin.recv(1024)
print(data.decode('utf8'))

asyncio 和 selector 的关系

selectors 则是 asyncio 的底层实现之一。asyncio实现的协程是由事件循环+ 任务组成的,而 selector 就是事件循环的重要依赖模块。

asyncio 使用了 selectors 模块来实现底层的并发 I/O 操作。通过将 selectors 的功能封装为 asyncio 提供的事件循环(Event Loop)和其他协程相关的工具。

Reference


Python 第三方模块之 APScheduler - 定时任务
https://flepeng.github.io/021-Python-31-Python-标准库-10-网络相关-Python-内置模块之-selector-IO-多路复用/
作者
Lepeng
发布于
2021年4月27日
许可协议