老师,帮我看看我的代码为什么需要两次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回答
-
我这里运行报了这个错误 你运行的时候有这个报错吗?012021-02-20 -
慕粉1056356323
2025-04-17
在readable unregister 2次 这个问题有后续吗?我也出现了这种问题 只有unregister 2次程序才会结束 但是我没有碰到老师贴图里的那个报错
012025-04-28
相似问题
我这里运行报了这个错误 你运行的时候有这个报错吗?