异步就是回调

异步 = 非阻塞+循环

select只能完成IO多路复用,不能完成异步

IO多路复用--->监听多个socket对象,这个过程是同步的

利用其特性可以开发异步模块

异步IO:非阻塞的socket + IO多路复用

自定义异步框架

  1. import socket
  2. import select
  3.  
  4. class HttpRequest(object):
  5. def __init__(self, sk, host, callback):
  6. self.socket = sk
  7. self.host = host
  8. self.callback = callback
  9. def fileno(self): # select监听的对象,只要内部有fileno()方法,并且返回fileno
  10. return self.socket.fileno()
  11.  
  12. class HttpResponse(object):
  13. def __init__(self, recv_data):
  14. self.recv_data = recv_data
  15. self.header_dict = {}
  16. self.body = None
  17. self.initialize()
  18.  
  19. def initialize(self):
  20. headers, body = self.recv_data.split(b'\r\n\r\n', 1)
  21. self.body = body
  22. header_list = headers.split(b'\r\n')
  23. for h in header_list:
  24. h_str = str(h, encoding='utf-8')
  25. v = h_str.split(':', 1)
  26. if len(v) == 2:
  27. self.header_dict[v[0]] = v[1]
  28.  
  29. class AsyncRequest(object):
  30. def __init__(self):
  31. self.conn = []
  32. self.connection = []
  33. def add_request(self, host, callback):
  34. try:
  35. sk = socket.socket()
  36. sk.setblocking(0)
  37. sk.connect((host, 80),)
  38. except BlockingIOError as e:
  39. pass
  40. # 把sk、host和callback封装起来,返回fd给select
  41. request = HttpRequest(sk, host, callback)
  42. self.conn.append(request)
  43. self.connection.append(request)
  44.  
  45. def run(self):
  46. while True:
  47. rlist, wlist, elist = select.select(self.conn, self.connection, self.conn, 0.05)
  48. for w in wlist:
  49. # 只要能循环到,表示socket和服务端已经连接成功
  50. print(w.host, '连接成功...')
  51. tpl = "GET / HTTP/1.0\r\nHost:%s\r\n\r\n" % (w.host,)
  52. w.socket.send(bytes(tpl, encoding='utf-8'))
  53. self.connection.remove(w)
  54. for r in rlist:
  55. recv_data = bytes()
  56. while True:
  57. try:
  58. chunck = r.socket.recv(8096)
  59. recv_data += chunck
  60. except Exception as e:
  61. break
  62. # 把返回的数据进行处理,然后交给回调函数
  63. response = HttpResponse(recv_data)
  64. r.callback(response)
  65. r.socket.close()
  66. self.conn.remove(r)
  67. if len(self.conn) == 0:
  68. break
  69.  
  70. def f1(response):
  71. print('保存到文件',response.header_dict)
  72.  
  73. def f2(response):
  74. print('保存到数据库', response.header_dict)
  75.  
  76. url_list = [
  77. {'host':'www.baidu.com','callback': f1},
  78. {'host':'cn.bing.com','callback': f2},
  79. {'host':'www.cnblogs.com','callback': f2},
  80. ]
  81.  
  82. req = AsyncRequest()
  83. for item in url_list:
  84. req.add_request(item['host'],item['callback'])
  85.  
  86. req.run()

自定义异步IO框架的更多相关文章

  1. 爬虫之多线程 多进程 自定义异步IO框架

    什么是进程? 进程是程序运行的实例,是系统进行资源分配和调度的一个独立单位,它包括独立的地址空间,资源以及1个或多个线程. 什么是线程? 线程可以看成是轻量级的进程,是CPU调度和分派的基本单位. 进 ...

  2. python---爬虫相关性能(各个异步模块的使用,和自定义异步IO模块)

    一:线程池,进程池等相关文章了解 python---基础知识回顾(十)进程和线程(py2中自定义线程池和py3中的线程池使用) python---基础知识回顾(十)进程和线程(协程gevent:线程在 ...

  3. Python并发编程之初识异步IO框架:asyncio 上篇(九)

    大家好,并发编程 进入第九篇. 通过前两节的铺垫(关于协程的使用),今天我们终于可以来介绍我们整个系列的重点 -- asyncio. asyncio是Python 3.4版本引入的标准库,直接内置了对 ...

  4. 自定义 异步 IO 非阻塞框架

    框架一 自定义Web异步非阻塞框架 suosuo.py #!/usr/bin/env python # -*- coding: utf-8 -*-# # __name__ = Web_Framewor ...

  5. Python学习---IO的异步[自定义异步IO]

    自定义IO异步基础知识: --所有的请求都基于socket实现,一个请求就是一个socket socket.setblocking(False) 不需要阻塞,一个请求完了发送另外一个,会报错,需解决 ...

  6. Python并发编程之实战异步IO框架:asyncio 下篇(十一)

    大家好,并发编程 进入第十一章. 前面两节,我们讲了协程中的单任务和多任务 这节我们将通过一个小实战,来对这些内容进行巩固. 在实战中,将会用到以下知识点: 多线程的基本使用 Queue消息队列的使用 ...

  7. Python并发编程之学习异步IO框架:asyncio 中篇(十)

    大家好,并发编程 进入第十章.好了,今天的内容其实还挺多的,我准备了三天,到今天才整理完毕.希望大家看完,有所收获的,能给小明一个赞.这就是对小明最大的鼓励了.为了更好地衔接这一节,我们先来回顾一下上 ...

  8. NoHttp封装--07 自定义异步任务框架

    MainActivity: public class MainActivity extends Activity implements View.OnClickListener { .... @Ove ...

  9. 异步IO框架:asyncio 中篇

    上一节我们首先介绍了,如何创建一个协程对象.主要有两种方法 通过async关键字, 通过@asyncio.coroutine 装饰函数. 然后有了协程对象,就需要一个事件循环容器来运行我们的协程.其主 ...

随机推荐

  1. laydate 只设置年月日,时分,不设置秒

    laydate.render({ elem: '#deadline_time' ,type: 'datetime' ,format: 'yyyy-MM-dd HH:mm' }); 设置了format, ...

  2. CSP前的板子们

    见窝的luogu博客qwq noip前的板子们

  3. 使用 python 进行微信好友分析

    使用 python 进行微信好友分析 1. 使用到的库 ① wxpy:初始化微信机器人 ② openpyxl:保存微信好友数据为Excel表格 ③ pyecharts:生成可视化的地图 ④ wordc ...

  4. 3.03定义常量之enum

    [注:本程序验证是使用vs2013版] #include <stdio.h> #include <stdlib.h> #include <string.h> #pr ...

  5. chmod: changing permissions of 'xxx': Operation not permitted

    众所周知,在linux系统中,权限最大的是root账号,但凡修改涉及到系统本身的重大权限的操作,都需要root的权限才能操作.但是有些时候也有root干不了的事情. 比如:chmod: changin ...

  6. python 多进程和协程配合使用

    一.需求分析 有一批key已经写入到3个txt文件中,每一个txt文件有30万行记录.现在需要读取这些txt文件,判断key是否在数据仓库中.(redis或者mysql) 为空的记录,需要写入到日志文 ...

  7. Mongodb 学习笔记(三) .net core SDK

    首先添加 Nuget包  MongoDB.Driver 创建一个Model. public class Student { public ObjectId _id { get; set; } publ ...

  8. JavaScript对象复制

    近期项目因为怕数据污染所以用到了js的对象复制 js里的对象都是继承自object,是引用类型,所以无法通过=号复制 所以整理了一些常用的复制方法,如下 一.通过JSON序列化和反序列化创建新的对象 ...

  9. nginx 开启 gzip 压缩

    现在使用vue或react开发的项目越来越多,纯js渲染,导致js体积越来越多,动辄就是几百上千kb,此时可以使用gzip的方式压缩js大小,减少请求时间与流量. 配置: http { gzip on ...

  10. Linux(常用)命令

    目录 Linux(常用)命令 系统信息 关机 (系统的关机.重启以及登出 ) 文件和目录 文件搜索 挂载一个文件系统 磁盘空间 用户和群组 文件的权限 - 使用 "+" 设置权限, ...