7.24 IO多路复用和协程代码笔记
1. 复习
# !/usr/bin/env python
# !--*--coding:utf-8 --*--
# !@Time :2018/7/23 11:49
# !@Author TrueNewBee
# 1.班级 姓名 作业的内容
# ftp
#
# 笔记 # 今天的内容
# 协程
# 网络IO模型
2.协程
# !/usr/bin/env python
# !--*--coding:utf-8 --*--
# !@Time :2018/7/23 11:52
# !@Author TrueNewBee
# 进程 启动多个进程 进程之间是由操作系统负责调用
# 线程 启动多个线程 真正被CPU执行的最小单位实际是线程
# 开启一个线程 创建一个线程 寄存器 堆栈
# 关闭一个线程
# 协程
# 本质上是一个线程
# 能够在多个任务之间切换来节省一些IO时间
# 实现并发的手段 # def consumer():
# """创建一个生成器"""
# while True:
# x = yield
# print('处理了数据', x)
#
#
# def producer():
# c = consumer()
# next(c)
# for i in range(10):
# print('生产了数据:', i)
# c.send(i)
#
#
# producer() # 真正的协程模块就是使用greenlet完成的切换
# from greenlet import greenlet
# # 不知道这个模块为何报错
# # 2018-7-23 12:34:39 吃饭去
#
#
# def eat():
# print('eating start')
# g2.switch() # 切换到play
# print('eating end')
# g2.switch()
#
#
# def play():
# print('playing start ')
# g1.switch()
# print('playing end')
#
#
# if __name__ == '__main__':
# # 用于切换线程
# g1 = greenlet(eat)
# g2 = greenlet(play)
# g1.switch() # 放在开头,是为了识别time (IO)
# from gevent import monkey; monkey.patch_all()
# import time
# import gevent
# import threading
#
#
# def eat():
# print(threading.current_thread()) # 查看线程名字
# print('eating start')
# time.sleep(1) # gevent 检测到停1s,则调到另外一个函数中
# print('eating end')
#
#
# def play():
# print(threading.current_thread())
# print('playing start ')
# time.sleep(1)
# print('playing end')
#
#
# if __name__ == '__main__':
# g1 = gevent.spawn(eat) # 开启协程
# g2 = gevent.spawn(play)
# g1.join()
# g2.join() # 进程和线程的任务切换由操作系统完成
# 协程任务之间的切换由程序(代码)完成 只有遇到协程模块能识别的IO操作的时候,程序才会进行任务切换实现并发效果 # 同步 和 异步 (网络操作常用协程)
# from gevent import monkey; monkey.patch_all()
# import time
# import gevent
#
#
# def task():
# time.sleep(1)
# print(12345)
#
#
# def sync():
# for i in range(10):
# task()
#
#
# def async():
# g_list = []
# for i in range(10):
# g = gevent.spawn(task)
# g_list.append(g)
# gevent.joinall(g_list) # for g in g_list :g.join()
#
#
# if __name__ == '__main__':
# sync()
# async() # 协程 : 能够在一个线程中实现并发效果的概念
# 能够规避一些任务中的IO操作
# 在任务的执行过程中,检测到IO就切换到其他任务 # 多线程 被弱化了
# 协程: 在一个线程上,提高cpu的利用率
# 协程相比于多线程的优势 切换的效率更快了 # 爬虫例子(正则基础)
# 请求过程中的IO等待
from gevent import monkey;monkey.patch_all()
import gevent
from urllib.request import urlopen def get_url(url1):
response = urlopen(url1)
content = response.read().decode('utf-8') # 有各式的
return len(content) url = {
'http://www.baidu.com',
'http://www.taobao.com',
'http://www.hao123.com',
}
g_list = []
for i in url:
g = gevent.spawn(get_url, i)
g_list.append(g)
gevent.joinall(g_list)
for g in g_list:
print(g.value)
# socket server
3.用协程写 socket_demo
socket
# !/usr/bin/env python
# !--*--coding:utf-8 --*--
# !@Time :2018/7/23 16:40
# !@Author TrueNewBee
# 用协程写 socket
# 用协程是最快最方便的 最省时间占用最小,代码间的转换
from gevent import monkey; monkey.patch_all()
import socket
import gevent def talk(conn1):
conn1.send(b'hello')
rec = conn.recv(1024).decode('utf-8')
print(rec)
conn.close() if __name__ == '__main__':
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()
while True:
conn, add = sk.accept()
gevent.spawn(talk, conn)
sk.close()
client
# !/usr/bin/env python
# !--*--coding:utf-8 --*--
# !@Time :2018/7/23 16:40
# !@Author TrueNewBee
import socket sk = socket.socket()
sk.connect(('127.0.0.1', 8080))
rec = sk.recv(1024).decode('utf-8')
print(rec)
msg = input('>>>>').encode('utf-8')
sk.send(msg)
sk.close()
4.IO模型 笔记
# !/usr/bin/env python
# !--*--coding:utf-8 --*--
# !@Time :2018/7/24 8:58
# !@Author TrueNewBee
# 同步 : 提交一个任务之后要等待这个任务执行完毕
# 异步 : 只管提交任务,不等待这个任务执行完毕就可以做其他事情
# 阻塞 : input urlopen() 在socket里面:recv() recvfrom() accept
# 非阻塞 : 除了阻塞的其他都是非阻塞 # 阻塞 线程 运行状态 --> 阻塞状态-->就绪
# 非阻塞 # IO多路复用
# select机制 Windows和linux 都是操作系统轮询每一个被监听的项,看是否读操作
# poll机制 linux 它可以监听的对象比select机制可以监听的多
# 随着监听项的增多,导致效率降低
# epoll机制 linux
5.非阻塞模型
socket
# !/usr/bin/env python
# !--*--coding:utf-8 --*--
# !@Time :2018/7/24 9:18
# !@Author TrueNewBee
# 非阻塞IO模型
# 单线程中非阻塞!(没有用协程!)
import socket sk = socket.socket()
sk.bind(('127.0.0.1', 8080))
sk.setblocking(False) # 默认True阻塞, False非阻塞
sk.listen()
conn_list = []
del_conn = [] # 存入失效连接的列表
while True:
# 接收异常 BlockingIOError 完成非阻塞
try:
conn, add = sk.accept() # 不阻塞,但没人连我会报错
print('建立连接了', add)
# msg = conn.recv(1024) # 不阻塞,但没有消息会报错
# print(msg)
conn_list.append(conn)
except BlockingIOError:
# 循环列表连接 看看是否有人发消息
for con in conn_list:
try:
msg = con.recv(1024) # 不阻塞,但没有消息会报错
if msg == b'':
del_conn.append(con) # 把失效的连接存到del_conn中
continue
print(msg)
con.send(b'bye bye')
except BlockingIOError:
pass
for con in del_conn:
con.close()
conn_list.remove(con) # 在conn_list中删除失效连接
del_conn.clear() # 清空删除列表
5. client
# !/usr/bin/env python
# !--*--coding:utf-8 --*--
# !@Time :2018/7/24 9:18
# !@Author TrueNewBee
# 非阻塞IO 多线程并发socket IO
import time
import socket
import threading def func():
sk = socket.socket()
sk.connect(('127.0.0.1', 8080))
sk.send(b'hello')
time.sleep(1)
msg = sk.recv(1024)
print(msg)
sk.close() for i in range(20):
threading .Thread(target=func).start()
6.IO多路复用
socket
# !/usr/bin/env python
# !--*--coding:utf-8 --*--
# !@Time :2018/7/24 11:51
# !@Author TrueNewBee
# IO多路复用 多并发!
import select
import socket sk = socket.socket()
sk.bind(('127.0.0.1', 8080))
sk.setblocking(False)
sk.listen() read_list = [sk] # 储存监听对象
while True: # [sk, conn] sk,发送链接 conn监听发送消息
r_list, w_list, x_list = select.select(read_list, [], [])
for i in r_list:
if i is sk:
conn, add = i.accept() # 没有sk, 有conn则会报错
read_list.append(conn)
else:
ret = i.recv(1024)
if ret == b'':
i.close()
read_list.remove(i)
continue
print(ret)
i.send(b'goodbye')
client
# !/usr/bin/env python
# !--*--coding:utf-8 --*--
# !@Time :2018/7/24 11:51
# !@Author TrueNewBee
import socket
import threading
import time def func():
sk = socket.socket()
sk.connect(('127.0.0.1', 8080))
sk.send(b'hello')
time.sleep(1)
sk.recv(1024)
sk.close() for i in range(20):
threading .Thread(target=func).start()
7.selector_dome
# !/usr/bin/env python
# !--*--coding:utf-8 --*--
# !@Time :2018/7/24 17:15
# !@Author TrueNewBee
# 服务端
from socket import *
import selectors
sel = selectors.DefaultSelector() def accept(server_fileobj, mask):
conn, addr = server_fileobj.accept()
sel.register(conn, selectors.EVENT_READ, read) def read(conn, mask):
try:
data = conn.recv(1024)
if not data:
print('closing', conn)
sel.unregister(conn)
conn.close()
return
conn.send(data.upper()+b'_SB')
except Exception:
print('closing', conn)
sel.unregister(conn)
conn.close() sk = socket(AF_INET, SOCK_STREAM)
sk.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
sk.bind(('127.0.0.1', 8088))
sk.listen(5)
sk.setblocking(False) # 设置socket的接口为非阻塞
# 相当于网select的读列表里append了一个文件句柄server_fileobj,并且绑定了一个回调函数accept
sel.register(sk, selectors.EVENT_READ, accept)
# 说白了就是,如果有人请求连接sk,就调用accept方法 while True:
events = sel.select() # 检测所有的sk,conn,是否有完成wait data的
for sel_obj, mask in events: # [sk]
callback = sel_obj.data # callback = accept
callback(sel_obj.fileobjmask) # accept(server_fileobj,1) # #客户端
# from socket import *
# c=socket(AF_INET, SOCK_STREAM)
# c.connect(('127.0.0.1',8088))
#
# while True:
# msg=input('>>: ')
# if not msg:continue
# c.send(msg.encode('utf-8'))
# data = c.recv(1024)
# print(data.decode('utf-8'))
#
# 基于selectors模块实现聊天
7.24 IO多路复用和协程代码笔记的更多相关文章
- IO多路复用,协程,
一.单线程的并发 import socket import select client1 = socket.socket() client1.setblocking(False) # 百度创建连接: ...
- IO多路复用和协程
1.IO多路复用 作用:检测多个socket是否已经发生变化(是否连接成功/是否已经获取数据) 什么是进程.线程.协程以及它们的区别? 进程是资源分配的最小单元,其作用是进行数据隔离, 线程是cpu调 ...
- IO多路复用、协程
一.铺垫:基于socket发送http请求 1.需求一:向百度发送请求搜索关键字“alex”,有如下两种方式: import requests ret = requests.get('https:// ...
- python中IO多路复用、协程
一.IO多路复用 IO多路复用:检测多个socket是否已经发生变化(是否已经连接成功/是否已经获取数据)(可读/可写) import socket def get_data(key): client ...
- Python全栈开发:协程代码实例
协程代码1 #!/usr/bin/env python # -*- coding;utf-8 -*- # 导入协程模块 """ 协程工作原理 ""&q ...
- I/O多路复用、协程、线程、进程
select注册fd,阻塞,当有fd状态改变时返回,确认对应的fd,做下一步处理.简单来说就是先注册,注册完后休眠并设置一个定时器醒来查看,有事件就通知来取,进行后续动作,没事件就继续睡,再设闹钟.用 ...
- python-socket和进程线程协程(代码展示)
socket # 一.socket # TCP服务端 import socket # 导入socket tcp_sk = socket.socket() # 实例化一个服务器对象 tcp_sk.bin ...
- 进程,线程,协程,io多路复用 总结
并发:要做到同时服务多个客户端,有三种技术 1. 进程并行,只能开到当前cpu个数的进程,但能用来处理计算型任务 ,开销最大 2. 如果并行不必要,那么可以考虑用线程并发,单位开销比进程小很多 线程: ...
- 小议Python3的原生协程机制
此文已由作者张耕源授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 在最近发布的 Python 3.5 版本中,官方正式引入了 async/await关键字.在 asyncio ...
随机推荐
- 细说Python2.x与3.x版本区别
Python的3.0版本,常被称为Python 3000,或简称Py3k.相对于Python的早期版本,这是一个较大的升级. 为了不带入过多的累赘,Python 3.0在设计的时候没有考虑向下相容 ...
- BIOS、EFI与UEFI详解
https://blog.csdn.net/Scythe666/article/details/79708293
- rpc框架thrift
跨语言的rpc框架 新建一个thrift文件 # ping service demoservice PingService { string ping(), ping函数的返回类型是字符串} serv ...
- Java利用数组随机抽取幸运观众
编写程序,事先将所有观众姓名输入数组,然后获得数组元素的总数量,最后在数组元素中随机抽取元素的下标,根据抽取的下标获得幸运观众的姓名. 思路如下: 定义输入框的按键事件,使用KeyEvent类的get ...
- error C4996: Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct
使用VS13 跟 google protocbuf时出现了这个问题:真蛋疼,用别人的东西你就说不安全,用你自己的东西时你怎么不说不安全来着! 解决方案 在protoc 生成的头文件中加上 #pr ...
- Axis2发布服务,支持Tomcat和Weblogic的SSHWeb项目部署
先说下遇到的问题,在SSHWeb项目中使用JDK自带的jar发布WebService(Endpoint.publish),在tomcat下可以正常发布,但是在Weblogic报奇葩错误,如Struts ...
- Web暴力破解--前端JS表单加密进行爆破
0x01 前言 常见的js实现加密的方式有:md5.base64.shal,写了一个简单的demo作为测试. 0x02 代码 login.html <!DOCTYPE HTML> < ...
- mybatis 之resultType="HashMap" parameterType="list"
<!-- 查询商品仓库信息 --> <select id="loadGoodsStock" resultType="HashMap" para ...
- 在javaweb的项目当中实现随机数字的生成
首先,需要在javaweb的项目当中新建一个Servlet文件,然后再web.xml中配置一下: 这样运行的时候就可以通过“http://localhost:8080/Response/Respons ...
- Python入门 学习笔记
十六进制:0x123 布尔运算:and, or, not 空值:None 注释:# raw字符串不需要转义:r'XXX' 多行字符:'''XXX''' 多行字符+raw字符串:r'''XXX''' U ...