自定义IO异步基础知识:

--所有的请求都基于socket实现,一个请求就是一个socket

socket.setblocking(False) 不需要阻塞,一个请求完了发送另外一个,会报错,需解决

--IO多路复用[是同步的请求]

IO多路复用有epoll, poll, select,知道epoll性能比其他几者要好[epoll先找到门牌号然后找人]。

IO多路复用本质上是在同一个线程或进程中,通过拨动开关的方式来执行多个IO操作。注意实际上每个IO操作都是独立进行的。只是由原来的一对一变成了多对多。

r,w,e = select.select([],[],[], 超时时间)  # socket有请求/响应前面的r,w,e都会接收到的

IO异步原理:

      IO异步的实现:本质则是【非阻塞Socket】+【IO多路复用】

IO异步的实现:本质则是【非阻塞Socket】+【IO多路复用】

import select
import socket
import time class AsyncTimeoutException(TimeoutError):
"""
请求超时异常类
"""
def __init__(self, msg):
self.msg = msg
super(AsyncTimeoutException, self).__init__(msg) # 封装了socket和buffer的对象
class HttpContext(object):
"""封装请求和相应的基本数据"""
def __init__(self, sock, host, port, method, url, data, callback, timeout=5):
"""
sock: 请求的客户端socket对象
host: 请求的主机名
port: 请求的端口
port: 请求的端口
method: 请求方式
url: 请求的URL
data: 请求时请求体中的数据
callback: 请求完成后的回调函数
timeout: 请求的超时时间
"""
self.sock = sock
self.callback = callback
self.host = host
self.port = port
self.method = method
self.url = url
self.data = data
self.timeout = timeout
self.__start_time = time.time()
self.__buffer = [] def is_timeout(self):
"""当前请求是否已经超时"""
current_time = time.time()
if (self.__start_time + self.timeout) < current_time:
return True def fileno(self):
"""请求sockect对象的文件描述符,用于select监听"""
return self.sock.fileno() def write(self, data):
"""在buffer中写入响应内容"""
self.__buffer.append(data) def finish(self, exc=None):
"""在buffer中写入响应内容完成,执行请求的回调函数"""
if not exc:
response = b''.join(self.__buffer)
self.callback(self, response, exc)
else:
self.callback(self, None, exc) def send_request_data(self):
content = """%s %s HTTP/1.0\r\nHost: %s\r\n\r\n%s""" % (
self.method.upper(), self.url, self.host, self.data,)
return content.encode(encoding='utf8') class AsyncRequest(object):
def __init__(self):
self.fds = []
self.connections = [] def add_request(self, host, port, method, url, data, callback, timeout):
"""创建一个要请求"""
client = socket.socket()
client.setblocking(False) # 不阻塞请求,不等待回应
try:
client.connect((host, port))
except BlockingIOError as e:
pass
# print('已经向远程发送连接的请求')
req = HttpContext(client, host, port, method, url, data, callback, timeout)
self.connections.append(req) # 封装HttpContext对象
self.fds.append(req) def check_conn_timeout(self):
"""检查所有的请求,是否有已经连接超时,如果有则终止"""
timeout_list = []
for context in self.connections:
if context.is_timeout():
timeout_list.append(context)
for context in timeout_list:
context.finish(AsyncTimeoutException('请求超时'))
self.fds.remove(context)
self.connections.remove(context) def running(self):
"""事件循环,用于检测请求的socket是否已经就绪,从而执行相关操作"""
while True:
r, w, e = select.select(self.fds, self.connections, self.fds, 0.05)
if not self.fds:
return for context in r:
sock = context.sock
while True:
try:
data = sock.recv(8096)
if not data:
self.fds.remove(context)
context.finish()
break
else:
context.write(data)
except BlockingIOError as e:
break
except TimeoutError as e:
self.fds.remove(context)
self.connections.remove(context)
context.finish(e)
break for context in w:
# 已经连接成功远程服务器,开始向远程发送请求数据
if context in self.fds:
data = context.send_request_data()
context.sock.sendall(data)
self.connections.remove(context) self.check_conn_timeout() if __name__ == '__main__':
def callback_func(context, response, ex):
"""
:param context: HttpContext对象,内部封装了请求相关信息
:param response: 请求响应内容
:param ex: 是否出现异常(如果有异常则值为异常对象;否则值为None)
:return:
"""
print(context, response, ex) obj = AsyncRequest()
# 基于TCP构造HTTP
url_list = [
{'host': 'www.google.com', 'port': 80, 'method': 'GET', 'url': '/', 'data': '', 'timeout': 5,
'callback': callback_func},
{'host': 'www.baidu.com', 'port': 80, 'method': 'GET', 'url': '/', 'data': '', 'timeout': 5, 'callback': callback_func},
{'host': 'www.bing.com', 'port': 80, 'method': 'GET', 'url': '/', 'data': '', 'timeout': 5, 'callback': callback_func},
]
for item in url_list:
print(item)
obj.add_request(**item)
obj.running()

Python学习---IO的异步[自定义异步IO]的更多相关文章

  1. python 学习笔记12(事件驱动、IO多路复用、异步IO)

    阻塞IO和非阻塞IO.同步IO和异步IO的区别 讨论背景:Linux环境下的network IO. 1.先决条件(几个重要概念) 1.1.用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32 ...

  2. Python学习-day10(番外篇) 阻塞IO 非阻塞IO 同步IO 异步IO

    这个章节的内容是关于IO的概念,谈一谈什么是 阻塞IO 非阻塞IO 同步IO 异步IO.以下摘要是我对这四种IO的一个形象理解. 场景是去去银行办理业务.节点有三个,1)到银行提交申请:2)取号:3) ...

  3. python学习之路-第八天-文件IO、储存器模块

    文件IO.储存器模块 文件IO 代码示例: # -*- coding:utf-8 -*- #! /usr/bin/python # filename:using_file.py poem = '''\ ...

  4. 【Python学习之九】asyncio—异步IO

    asyncio 这是python3.4引入的标准库,直接内置对异步IO的支持.asyncio的编程模型就是一个消息循环.从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程 ...

  5. python 学习笔记九 队列,异步IO

    queue (队列) 队列是为线程安全使用的. 1.先入先出 import queue #测试定义类传入队列 class Foo(object): def __init__(self,n): self ...

  6. python学习笔记之四-多进程&多线程&异步非阻塞

    ProcessPoolExecutor对multiprocessing进行了高级抽象,暴露出简单的统一接口. 异步非阻塞 爬虫 对于异步IO请求的本质则是[非阻塞Socket]+[IO多路复用]: & ...

  7. python学习之算法、自定义模块、系统标准模块(上)

    算法.自定义模块.系统标准模块(time .datetime .random .OS .sys .hashlib .json和pickle) 一:算法回顾: 冒泡算法,也叫冒泡排序,其特点如下: 1. ...

  8. python学习笔记:模块——自定义模块的3种导入方式

    一.定义 模块就是用一堆的代码实现了一些功能的代码的集合,通常一个或者多个函数写在一个.py文件里,而如果有些功能实现起来很复杂,那么就需要创建n个.py文件,这n个.py文件的集合就是模块.如果不懂 ...

  9. Python学习---django多对多自定义第三方表180206

    案例一: # version: python3.2.5 # author: 'FTL1012' # time: 2018/2/6 16:25 from django.db import models ...

随机推荐

  1. 从入门到不放弃系列之Koa2

    一.Koa2入门 本来是想Express入门的,但是既然都是要学,干嘛不学最新的呢? 其实我想说,我本来只是想学个小程序开发,现在已经陆陆续续开了好多坑了.. 本文参考廖雪峰教程 二.Async 最新 ...

  2. PTA (Advanced Level) 1027 Colors in Mars

    Colors in Mars People in Mars represent the colors in their computers in a similar way as the Earth ...

  3. Entity Framework取消修改

    最近碰到一个场景:在Entity Framework保存错误的时候,需要将该错误记录在DB中.因为DB在savechange的时候会继续保存之前的数据,所以一直会报错,无法保存错误日志. 这就需要实现 ...

  4. 糗事之 -- 用ssh公钥实现免密码登录

    前言:工作原因,每天都会登录好多次服务器,每次都是ssh root@192.168..... 然后输入密码,来来回回输几次真是很烦啊. 问题:怎么可以在每次ssh连接服务器时不用输入密码,直接登录? ...

  5. 红色警戒3原版V1.00基址大全

    127.0.0.1 servserv.generals.ea.com ===================================1.04 基址变化 00DFBD74=>DFCDF4 ...

  6. golang基础--func函数

    函数function Go函数不支持 嵌套, 重载和默认参数 支持以下特性: 无须声明原型,不定长度长度变参,多返回值,命名返回值参数,匿名函数,闭包 定义函数使用关键字func,且左侧大括号不能另起 ...

  7. Matlab基本数学应用

    基本线性代数 [R jb]=rref(A)将A化为行最简型矩阵.R为所得行最简型矩阵,jb是一个向量显示每行首非0元所在列号. inv(A)求方阵A的逆,注意结果可能出现错误.当结果中出现Inf和Na ...

  8. mongodb自学

    http://www.runoob.com/mongodb/mongodb-databases-documents-collections.html

  9. elasticsearch环境搭建

    学习elasticsearch有一段时间了,整理一些学习的笔记以备忘. 以下内容都是在windows环境下的操作. 一,安装一个较新版本的java,我本地安装的java 8. 二,安装elastics ...

  10. Spring学习之路

    (一)搭建Spring.NET环境常见的DLL 1.spring.core --整个框架的基础,实现了依赖注入的功能 2.Spring.AOP--提供面向方面编程(aop)的支持 3.Spring.D ...