Python之selectors模块

官方文档:https://docs.python.org/3/library/selectors.html

参考链接:
https://www.cnblogs.com/zzzlw/p/9384308.html
https://blog.csdn.net/cswhl/article/details/111572702
基本介绍 https://www.cnblogs.com/yinheyi/p/8127871.html
实验演示 https://www.cnblogs.com/xybaby/p/6406191.html#_label_2
详细讲解 http://aju.space/2017/07/31/Drive-into-python-asyncio-programming-part-1.html
官方文档selecotors https://docs.python.org/3/library/selectors.html
官方文档select https://docs.python.org/3/library/select.html

IO模型:https://www.cnblogs.com/-wenli/p/10644511.html

selectors是一个python自带的高性能、IO复用模块,可以用来替代select模块。

测试代码:

#!/usr/bin/python3

import socket
from urllib.parse import urlparse
# DefaultSelector默认选择器,使用当前平台上可用的最高效的实现(select/poll/epoll)
from selectors import DefaultSelector, EVENT_READ, EVENT_WRITE


class Client(object):
    '''负责连接、 发送和接受'''
    def __init__(self, url):
        url = urlparse(url)
        self.host, self.path = url.netloc, [url.path, '/'][url.path == '']
        self.sock = socket.socket()
        self.sock.setblocking(False)
        self.data = b''
        try:
            self.sock.connect((self.host, 80))
        except BlockingIOError as ret:  # noqa
            pass

    def send_request(self):
        self.sock.send(
            "GET {} HTTP/1.1\r\nHost: {}\r\nConnection:close\r\n\r\n".format(
                self.path, self.host).encode('utf-8'))

    def recv_response(self):
        rev = self.sock.recv(1024)
        if rev:
            self.data += rev
            return True
        return False

    def end(self):
        html_body = self.data.split(b'\r\n\r\n')[1]
        self.sock.close()
        print(html_body)
        print('\n')
        return html_body


'''select + callback + eventLoop:单线程并发
只处理准备好socket事件,无需等待I/O;省去了线程切换的开销
回调模式:底层调用高层'''


class Select(object):
    '''创建selector,负责注册和取消注册socket读写事件、'''

    def __init__(self):
        self.selector = DefaultSelector()
        self.clients = {}

    def startListening(self, client):
        # add client,monitor socked wtite event
        self.clients[client.sock] = client
        # 注册socket写事件
        self.selector.register(client.sock, EVENT_WRITE, self.connected)

    def connected(self, key):
        # connect host,and monitor socket read event
        self.selector.unregister(key.fileobj)
        sock = key.fileobj
        self.clients[sock].send_request()
        self.selector.register(sock, EVENT_READ, self.do_read)

    def do_read(self, key):
        # read data ,if data is empty, then unregister socket and end
        sock = key.fileobj
        client = self.clients[sock]
        if client.recv_response():
            return
        self.selector.unregister(sock)
        client.end()


def event_loop():
    while True:
        events = sel.selector.select()
        for key, mask in events:
            print(key, mask)
            callback = key.data
            callback(key)


if __name__ == '__main__':
    urls = ['http://www.baidu.com', 'http://httpbin.org/']
    sel = Select()
    for url in urls:
        sel.startListening(Client(url))
    event_loop()
    sel.selector.close()

原理介绍: