1-了解socket使用
def get_data(key):
# 创建一个socket对象
client = socket.socket()
# 跟百度创建连接 处于堵塞状态
client.connect(('www.baidu.com', 80))
# 告诉百度我要什么
client.sendall(b"GET /s?wd=%s HTTP/1.0\r\nhost: www.baidu.com\r\n\r\n" % key)
# 接收百度发给我的信息
chunk_list = []
while True:
chunk = client.recv(1000)
if not chunk:
break
chunk_list.append(chunk)
body = b"".join(chunk_list).decode('utf-8')
print(body)
if __name__ == '__main__':
list_1 = ['alex', 'db', 'sb']
# for x in list_1:
# get_data(x)
for x in list_1:
print(x)
t = threading.Thread(target=get_data, args=(x,)) # 创建线程
t.start()
2-了解非堵塞
如何让socket 不堵塞
setblocking(False) 这样 socket 就不堵塞了
但是也是存在一些问题,报错后面都会 那那就需要用try捕获
try:
client.connect(('www.baidu.com', 80)) # 执行报错
except BlockingIOError:
pass
3-IO多路复用
它是用来监控的 数据的读于写 enmm应该IO数据
方式1 : select
方式2:pool
方式3:epool 不过后两种win用不了
import select
r_list, w_list, e_list = select.select(socket_list, conn_list, [], 0.005)
# r_list 表示可以可以读
#w_list 表示可写
4-IO多路复用示例
需要学习的是封装思想
为什么要学习封装思想 ? 因这样子可以保留以前的数据不需要进行修改
import socket
import select
class Req(object):
def __init__(self, sk, func):
self.sk = sk
self.func = func
def fileno(self):
return self.sk.fileno()
class NB(object):
def __init__(self):
self.conn_list = []
self.socket_list = []
def add(self, url, func):
client = socket.socket()
client.setblocking(False)
try:
client.connect((url, 80))
except BlockingIOError as e:
pass
obj = Req(client, func)
self.conn_list.append(obj)
self.socket_list.append(obj)
def run(self):
while True:
r_list, w_list, e_list = select.select(self.socket_list, self.conn_list, [], 0.005) # 检测是否发生变化
# w_list有数据 表示已经连接成功了
for sk in w_list:
sk.sk.sendall(b"GET /s?wd=li HTTP/1.0\r\nhost:www.baidu.com\r\n\r\n")
self.conn_list.remove(sk)
for sk in r_list:
sk_list = []
while True:
try:
response = sk.sk.recv(1000)
if not response:
break
sk_list.append(response)
except BlockingIOError as e:
break
data = b"".join(sk_list)
sk.func(data)
sk.sk.close()
self.socket_list.remove(sk)
if not self.socket_list:
break
def baidu_response(data):
print('百度', data)
def bing_response(data):
print('bing', data)
def sogou_response(data):
print('搜狗', data)
t1 = NB()
t1.add("www.baidu.com", baidu_response)
t1.add("cn.bing.com", bing_response)
t1.add("wwww.sogou.com", sogou_response)
t1.run()
5-认识协程
线程是不存在的
协程是 简单说微线程
对线程进行分片 理解 让程序自由执行
单纯的协程是没什么用的 需要和IO切换一起才厉害
import greenlet # 这才是协程模块
def f1():
print('你好')
gr2.switch()
print(22)
gr2.switch()
def f2():
print('hello')
gr1.switch()
print(11)
# 创建协程
gr1 = greenlet.greenlet(f1)
gr2 = greenlet.greenlet(f2)
IO切换
gevent 模块
记得 patch_all() 一定要在前面 不然就会报错
from gevent import monkey
monkey.patch_all() # 遇到IO就切换
import gevent
import requests
def get_page(url):
req = requests.get(url)
print(url, req.content)
def get_page1(url):
req = requests.get(url)
print(url, req.content)
def get_page2(url):
req = requests.get(url)
print(url, req.content)
gevent.joinall([
gevent.spawn(get_page, 'https://www.baidu.com'),
gevent.spawn(get_page1, 'https://translate.google.cn'),
gevent.spawn(get_page2, 'https://www.bilibili.com'),
])
# 这里就在调用了