1. 程式人生 > >select + 回調 + 事件循環

select + 回調 + 事件循環

() back bsp select() 調用 回調函數 def 需要 AI

#1. epoll並不代表一定比select好
# 在並發高的情況下,連接活躍度不是很高, epoll比select
# 並發性不高,同時連接很活躍, select比epoll好

#通過非阻塞io實現http請求
# select + 回調 + 事件循環
#  並發性高
# 使用單線程

import socket
from urllib.parse import urlparse
from selectors import DefaultSelector, EVENT_READ, EVENT_WRITE


selector = DefaultSelector()
#使用select完成http請求
urls = [] stop = False class Fetcher: def connected(self, key): selector.unregister(key.fd) self.client.send("GET {} HTTP/1.1\r\nHost:{}\r\nConnection:close\r\n\r\n".format(self.path, self.host).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) self.client.close() urls.remove(self.spider_url)
if not urls: global stop stop = True def get_url(self, url): self.spider_url = url url = urlparse(url) self.host = url.netloc self.path = url.path self.data = b"" if self.path == "": self.path = "/" # 建立socket連接 self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.client.setblocking(False) try: self.client.connect((self.host, 80)) # 阻塞不會消耗cpu except BlockingIOError as e: pass #註冊 selector.register(self.client.fileno(), EVENT_WRITE, self.connected) def loop(): #事件循環,不停的請求socket的狀態並調用對應的回調函數 #1. select本身是不支持register模式 #2. socket狀態變化以後的回調是由程序員完成的 while not stop: ready = selector.select() for key, mask in ready: call_back = key.data call_back(key) #回調+事件循環+select(poll\epoll) if __name__ == "__main__": fetcher = Fetcher() import time start_time = time.time() for url in range(20): url = "http://shop.projectsedu.com/goods/{}/".format(url) urls.append(url) fetcher = Fetcher() fetcher.get_url(url) loop() print(time.time()-start_time) # def get_url(url): # #通過socket請求html # url = urlparse(url) # host = url.netloc # path = url.path # if path == "": # path = "/" # # #建立socket連接 # client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # client.setblocking(False) # try: # client.connect((host, 80)) #阻塞不會消耗cpu # except BlockingIOError as e: # pass # # #不停的詢問連接是否建立好, 需要while循環不停的去檢查狀態 # #做計算任務或者再次發起其他的連接請求 # # while True: # try: # client.send("GET {} HTTP/1.1\r\nHost:{}\r\nConnection:close\r\n\r\n".format(path, host).encode("utf8")) # break # except OSError as e: # pass # # # data = b"" # while True: # try: # d = client.recv(1024) # except BlockingIOError as e: # continue # if d: # data += d # else: # break # # data = data.decode("utf8") # html_data = data.split("\r\n\r\n")[1] # print(html_data) # client.close()

select + 回調 + 事件循環