协程和IO模型
为什么会有协程的存在?
线程的创建也会占用一定的时间,所以直接用协程模块儿来手动切换,就会剩下来创建线程的时间
利用协程写爬虫:
from gevent import monkey monkey.patch_all() import requests import gevent def get_url(url): return len(requests.get(url).content.decode()) g1 = gevent.spawn(get_url, "https://www.baidu.com") g2 = gevent.spawn(get_url, "https://www.hao123.com") g3 = gevent.spawn(get_url, "https://www.sogo.com") g4 = gevent.spawn(get_url, "https://www.taobao.com") gevent.joinall([g1, g2, g3, g4]) print(g1.value) print(g2.value) print(g3.value) print(g4.value)
IO模型:
平常正常写socket的就是阻塞IO模型
非阻塞IO模型:
server端: import socket sk = socket.socket() sk.bind(("127.0.0.1", 9000)) sk.setblocking(False) sk.listen() con_l = [] del_con_l = [] while 1: try: conn, addr = sk.accept() print("和{}建立连接成功".format(addr)) con_l.append(conn) except: for con in con_l: try: info = con.recv(1024).decode() if info == "": del_con_l.append(con) continue print(info) con.send(b"byebye") except: pass for con in del_con_l: con.close() con_l.remove(con) del_con_l.clear() client端: import time from threading import Thread import socket def func(): sk = socket.socket() sk.connect(("127.0.0.1", 9000)) time.sleep(10) sk.send(b"hello") info = sk.recv(1024).decode() print(info) sk.close() if __name__ == '__main__': for i in range(20): Thread(target=func).start()
多路复用IO模型:
server端: import socket import select sk = socket.socket() sk.bind(("127.0.0.1", 8090)) sk.setblocking(False) sk.listen() read_lst = [sk] while 1: r_lst, w_lst, x_lst = select.select(read_lst, [], []) for i in r_lst: if i is sk: conn, addr = i.accept() read_lst.append(conn) else: info = i.recv(1024).decode() if info == "": i.close() read_lst.remove(i) continue print(info) i.send(b"goodbye") client: import time from threading import Thread import socket def func(): sk = socket.socket() sk.connect(("127.0.0.1", 8090)) time.sleep(5) sk.send(b"hello") info = sk.recv(1024).decode() print(info) sk.close() if __name__ == '__main__': for i in range(20): Thread(target=func).start()
各种IO模型的比较: