老师,帮我看看我的代码为什么需要两次selector.unregister操作?

来源:12-4 select+回调+事件循环获取html-2

邱晨100

2021-02-18

老师好,我先贴一下我的代码:

# -*- coding: utf-8 -*-


import socket
from urllib.parse import urlparse
from selectors import DefaultSelector, EVENT_READ, EVENT_WRITE
# windows上默认选择select linux上默认epoll

# 使用select完成http请求

selector = DefaultSelector()


class Fetcher:
    def __init__(self, url):
        url = urlparse(url)
        self.path = '/' if url.path == '' else url.path
        self.host = url.netloc
        self.data = b''
        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.client.setblocking(False)

    def connected(self, key):
        selector.unregister(key.fd)
        self.client.send(f'GET {self.path} HTTP/1.1\r\nHost:{self.host}\r\n'
                         f'Connection:close\r\n\r\n'.encode('utf8'))
        selector.register(self.client.fileno(), EVENT_READ, self.readable)

    def readable(self, key):
        d = self.client.recv(1024)
        if d:
            self.data += d
        else:
            selector.unregister(key.fd)
            data = self.data.decode('utf8')
            html_data = data.split('\r\n\r\n')[1]
            print(html_data)
            selector.unregister(key.fd)
            self.client.close()

    def get_url(self):
        # 通过socket请求html
        try:
            self.client.connect((self.host, 80))
        except BlockingIOError as e:
            pass
        # 注册
        selector.register(self.client.fileno(), EVENT_WRITE, self.connected)


def loop():
    """事件循环,不停的请求socket的状态并调用对应的回调函数"""
    while True:
        ready = selector.select()
        for key, mask in ready:
            call_back = key.data
            call_back(key)
    # 回调+事件循环


if __name__ == '__main__':
    fetcher = Fetcher('http://www.baidu.com')
    fetcher.get_url()
    loop()

readable方法里面需要两次执行selector.unregister(key.fd)才能正常结束程序,否则程序会一直循环着不结束。
有两点我很奇怪,
第一,unregister需要两次才有效?这是个bug嘛?
第二,我还没有设置一个全局变量,来控制跳出最外层的大循环,来结束程序,为什么在我读完整个内容之后,做了两次unregister就结束程序了?在selector里面注销fd和外层终止循环结束程序看上去没啥关系啊。

写回答

2回答

bobby

2021-02-20

//img.mukewang.com/szimg/6030ef9f097ac94612630305.jpg 我这里运行报了这个错误 你运行的时候有这个报错吗?

0
1
邱晨100
是的啊
2021-02-20
共1条回复

慕粉1056356323

2025-04-17

readable unregister 2次 这个问题有后续吗?我也出现了这种问题 只有unregister 2次程序才会结束 但是我没有碰到老师贴图里的那个报错

0
1
bobby
有没有逐行代码调试过?
2025-04-28
共1条回复

Python3高级核心技术97讲,高级进阶的必学课程

socket编程/多线程/多进程/线程池/asyncio并发编程/协程和异步IO

2143 学习 · 552 问题

查看课程