自定义异步IO框架
异步就是回调
异步 = 非阻塞+循环
select只能完成IO多路复用,不能完成异步
IO多路复用--->监听多个socket对象,这个过程是同步的
利用其特性可以开发异步模块
异步IO:非阻塞的socket + IO多路复用
自定义异步框架
- import socket
- import select
- class HttpRequest(object):
- def __init__(self, sk, host, callback):
- self.socket = sk
- self.host = host
- self.callback = callback
- def fileno(self): # select监听的对象,只要内部有fileno()方法,并且返回fileno
- return self.socket.fileno()
- class HttpResponse(object):
- def __init__(self, recv_data):
- self.recv_data = recv_data
- self.header_dict = {}
- self.body = None
- self.initialize()
- def initialize(self):
- headers, body = self.recv_data.split(b'\r\n\r\n', 1)
- self.body = body
- header_list = headers.split(b'\r\n')
- for h in header_list:
- h_str = str(h, encoding='utf-8')
- v = h_str.split(':', 1)
- if len(v) == 2:
- self.header_dict[v[0]] = v[1]
- class AsyncRequest(object):
- def __init__(self):
- self.conn = []
- self.connection = []
- def add_request(self, host, callback):
- try:
- sk = socket.socket()
- sk.setblocking(0)
- sk.connect((host, 80),)
- except BlockingIOError as e:
- pass
- # 把sk、host和callback封装起来,返回fd给select
- request = HttpRequest(sk, host, callback)
- self.conn.append(request)
- self.connection.append(request)
- def run(self):
- while True:
- rlist, wlist, elist = select.select(self.conn, self.connection, self.conn, 0.05)
- for w in wlist:
- # 只要能循环到,表示socket和服务端已经连接成功
- print(w.host, '连接成功...')
- tpl = "GET / HTTP/1.0\r\nHost:%s\r\n\r\n" % (w.host,)
- w.socket.send(bytes(tpl, encoding='utf-8'))
- self.connection.remove(w)
- for r in rlist:
- recv_data = bytes()
- while True:
- try:
- chunck = r.socket.recv(8096)
- recv_data += chunck
- except Exception as e:
- break
- # 把返回的数据进行处理,然后交给回调函数
- response = HttpResponse(recv_data)
- r.callback(response)
- r.socket.close()
- self.conn.remove(r)
- if len(self.conn) == 0:
- break
- def f1(response):
- print('保存到文件',response.header_dict)
- def f2(response):
- print('保存到数据库', response.header_dict)
- url_list = [
- {'host':'www.baidu.com','callback': f1},
- {'host':'cn.bing.com','callback': f2},
- {'host':'www.cnblogs.com','callback': f2},
- ]
- req = AsyncRequest()
- for item in url_list:
- req.add_request(item['host'],item['callback'])
- req.run()
自定义异步IO框架的更多相关文章
- 爬虫之多线程 多进程 自定义异步IO框架
什么是进程? 进程是程序运行的实例,是系统进行资源分配和调度的一个独立单位,它包括独立的地址空间,资源以及1个或多个线程. 什么是线程? 线程可以看成是轻量级的进程,是CPU调度和分派的基本单位. 进 ...
- python---爬虫相关性能(各个异步模块的使用,和自定义异步IO模块)
一:线程池,进程池等相关文章了解 python---基础知识回顾(十)进程和线程(py2中自定义线程池和py3中的线程池使用) python---基础知识回顾(十)进程和线程(协程gevent:线程在 ...
- Python并发编程之初识异步IO框架:asyncio 上篇(九)
大家好,并发编程 进入第九篇. 通过前两节的铺垫(关于协程的使用),今天我们终于可以来介绍我们整个系列的重点 -- asyncio. asyncio是Python 3.4版本引入的标准库,直接内置了对 ...
- 自定义 异步 IO 非阻塞框架
框架一 自定义Web异步非阻塞框架 suosuo.py #!/usr/bin/env python # -*- coding: utf-8 -*-# # __name__ = Web_Framewor ...
- Python学习---IO的异步[自定义异步IO]
自定义IO异步基础知识: --所有的请求都基于socket实现,一个请求就是一个socket socket.setblocking(False) 不需要阻塞,一个请求完了发送另外一个,会报错,需解决 ...
- Python并发编程之实战异步IO框架:asyncio 下篇(十一)
大家好,并发编程 进入第十一章. 前面两节,我们讲了协程中的单任务和多任务 这节我们将通过一个小实战,来对这些内容进行巩固. 在实战中,将会用到以下知识点: 多线程的基本使用 Queue消息队列的使用 ...
- Python并发编程之学习异步IO框架:asyncio 中篇(十)
大家好,并发编程 进入第十章.好了,今天的内容其实还挺多的,我准备了三天,到今天才整理完毕.希望大家看完,有所收获的,能给小明一个赞.这就是对小明最大的鼓励了.为了更好地衔接这一节,我们先来回顾一下上 ...
- NoHttp封装--07 自定义异步任务框架
MainActivity: public class MainActivity extends Activity implements View.OnClickListener { .... @Ove ...
- 异步IO框架:asyncio 中篇
上一节我们首先介绍了,如何创建一个协程对象.主要有两种方法 通过async关键字, 通过@asyncio.coroutine 装饰函数. 然后有了协程对象,就需要一个事件循环容器来运行我们的协程.其主 ...
随机推荐
- laydate 只设置年月日,时分,不设置秒
laydate.render({ elem: '#deadline_time' ,type: 'datetime' ,format: 'yyyy-MM-dd HH:mm' }); 设置了format, ...
- CSP前的板子们
见窝的luogu博客qwq noip前的板子们
- 使用 python 进行微信好友分析
使用 python 进行微信好友分析 1. 使用到的库 ① wxpy:初始化微信机器人 ② openpyxl:保存微信好友数据为Excel表格 ③ pyecharts:生成可视化的地图 ④ wordc ...
- 3.03定义常量之enum
[注:本程序验证是使用vs2013版] #include <stdio.h> #include <stdlib.h> #include <string.h> #pr ...
- chmod: changing permissions of 'xxx': Operation not permitted
众所周知,在linux系统中,权限最大的是root账号,但凡修改涉及到系统本身的重大权限的操作,都需要root的权限才能操作.但是有些时候也有root干不了的事情. 比如:chmod: changin ...
- python 多进程和协程配合使用
一.需求分析 有一批key已经写入到3个txt文件中,每一个txt文件有30万行记录.现在需要读取这些txt文件,判断key是否在数据仓库中.(redis或者mysql) 为空的记录,需要写入到日志文 ...
- Mongodb 学习笔记(三) .net core SDK
首先添加 Nuget包 MongoDB.Driver 创建一个Model. public class Student { public ObjectId _id { get; set; } publ ...
- JavaScript对象复制
近期项目因为怕数据污染所以用到了js的对象复制 js里的对象都是继承自object,是引用类型,所以无法通过=号复制 所以整理了一些常用的复制方法,如下 一.通过JSON序列化和反序列化创建新的对象 ...
- nginx 开启 gzip 压缩
现在使用vue或react开发的项目越来越多,纯js渲染,导致js体积越来越多,动辄就是几百上千kb,此时可以使用gzip的方式压缩js大小,减少请求时间与流量. 配置: http { gzip on ...
- Linux(常用)命令
目录 Linux(常用)命令 系统信息 关机 (系统的关机.重启以及登出 ) 文件和目录 文件搜索 挂载一个文件系统 磁盘空间 用户和群组 文件的权限 - 使用 "+" 设置权限, ...