1. # -*- coding: utf-8 -*-
  2. # @Time : 2018/12/15 18:55
  3. # @File : coroutine.py
  4.  
  5. #一个简单的 Coroutine 框架
  6.  
  7. import socket # on top of TCP
  8. import time
  9. from selectors import DefaultSelector, EVENT_WRITE, EVENT_READ
  10. # select: System Call -----> watch the readiness of a unix-file(socket) i/o
  11. # only socket is possible in Windows
  12. # non-blocking socket
  13.  
  14. selector = DefaultSelector()
  15.  
  16. class Future: # ~=Promise, return the caller scope a promise
  17. # about something in the future
  18. def __init__(self):
  19. self.callbacks = []
  20.  
  21. def resolve(self): # on future event callback
  22. for func in self.callbacks:
  23. func()
  24.  
  25. class Task: # responsible for calling next() on generators
  26. # in charge of the async functions
  27. def __init__(self, gen, eventLoop):
  28. self.gen = gen
  29. self.step()
  30.  
  31. def step(self): # go to next step/next yield
  32. try:
  33. f = next(self.gen)
  34. f.callbacks.append(self.step)
  35. except StopIteration as e:
  36. # Task is finished
  37. eventLoop.n_task -= 1
  38.  
  39. class EventLoop:
  40. def __init__(self):
  41. self.n_task = 0
  42.  
  43. def add_task(self, generator):
  44. self.n_task += 1
  45. Task(generator, self)
  46.  
  47. def start(self):
  48. while self.n_task > 0:
  49. events = selector.select()
  50. for event, mask in events:
  51. f = event.data
  52. f.resolve()
  53.  
  54. def pause(s, event):
  55. f = Future()
  56. selector.register(s.fileno(), event, data=f)
  57. yield f # pause this function
  58.  
  59. def resume(s):
  60. selector.unregister(s.fileno())
  61.  
  62. def async_await(s, event):
  63. yield from pause(s, event)
  64. resume(s)
  65.  
  66. def async_get(path):
  67. s = socket.socket()
  68. s.setblocking(False)
  69. try:
  70. s.connect(('localhost', 3000))
  71. except BlockingIOError as e:
  72. print(e)
  73.  
  74. yield from async_await(s, EVENT_WRITE)
  75.  
  76. request = 'GET %s HTTP/1.0\r\n\r\n' % path
  77. s.send(request.encode())
  78.  
  79. totalReceived = []
  80. while True:
  81. yield from async_await(s, EVENT_READ)
  82.  
  83. received = s.recv(1000)
  84. if received:
  85. totalReceived.append(received)
  86. else:
  87. body = (b''.join(totalReceived)).decode()
  88. print('--------------------------------------')
  89. print(body)
  90. print('--------------------------------------', 'Byte Received:', len(body), '\n\n')
  91. return
  92.  
  93. if __name__ == '__main__':
  94. start = time.time()
  95. eventLoop = EventLoop()
  96.  
  97. for i in range(50):
  98. eventLoop.add_task(async_get('/super-slow'))
  99.  
  100. eventLoop.start()
  101.  
  102. print('%.1f sec' % (time.time() - start))

  

[记录]python的简单协程框架(回调+时间循环+select)的更多相关文章

  1. [转载]Python 3.5 协程究竟是个啥

    http://blog.rainy.im/2016/03/10/how-the-heck-does-async-await-work-in-python-3-5/ [译] Python 3.5 协程究 ...

  2. [译] Python 3.5 协程究竟是个啥

    转自:http://blog.rainy.im/2016/03/10/how-the-heck-does-async-await-work-in-python-3-5/ [译] Python 3.5 ...

  3. Python IO 多路复用 \协程

    IO 多路复用 作用:  检测多个socket是否已经发生变化(是否已经连接成功/是否已经获取数据) 即(可读/可写) IO请求时 解决并发  :  单线程 def get_data(key): cl ...

  4. python线程、协程、I/O多路复用

    目录: 并发多线程 协程 I/O多路复用(未完成,待续) 一.并发多线程 1.线程简述: 一条流水线的执行过程是一个线程,一条流水线必须属于一个车间,一个车间的运行过程就是一个进程(一个进程内至少一个 ...

  5. python中的协程并发

    python asyncio 网络模型有很多中,为了实现高并发也有很多方案,多线程,多进程.无论多线程和多进程,IO的调度更多取决于系统,而协程的方式,调度来自用户,用户可以在函数中yield一个状态 ...

  6. python爬虫——多线程+协程(threading+gevent)

    上一篇博客中我介绍了如何将爬虫改造为多进程爬虫,但是这种方法对爬虫效率的提升不是非常明显,而且占用电脑cpu较高,不是非常适用于爬虫.这篇博客中,我将介绍在爬虫中广泛运用的多线程+协程的解决方案,亲测 ...

  7. 第十一章:Python高级编程-协程和异步IO

    第十一章:Python高级编程-协程和异步IO Python3高级核心技术97讲 笔记 目录 第十一章:Python高级编程-协程和异步IO 11.1 并发.并行.同步.异步.阻塞.非阻塞 11.2 ...

  8. Python中异步协程的使用方法介绍

    1. 前言 在执行一些 IO 密集型任务的时候,程序常常会因为等待 IO 而阻塞.比如在网络爬虫中,如果我们使用 requests 库来进行请求的话,如果网站响应速度过慢,程序一直在等待网站响应,最后 ...

  9. Python中Paramiko协程方式详解

    什么是协程 协程我们可以看做是一种用户空间的线程. 操作系统对齐存在一无所知,需要用户自己去调度. 比如说进程,线程操作系统都是知道它们存在的.协程的话是用户空间的线程,操作系统是不知道的. 为什么要 ...

随机推荐

  1. 数据可视化图表ECharts

    介绍: ECharts是一个基于ZRender(轻量级Canvas类库)的纯javascript图表库,提供可交互.个性化的数据可视化图表. ECharts提供了折线图.柱状图.散点图.饼图.K线图, ...

  2. 反射:获取枚举类型的Name,Value,Description

    [Obsolete("请使用新的方法XXX")] //使用Obsolete特性来告诉使用者这是一个过期的方法 private static void Test() { Type t ...

  3. spring.net的简单使用(二)资源配置

    主要对资源配置做进一步的解析. 对资源位置的配置是在spring节点的context下,resource节点配置. spring.net的资源是可以设置在三种不同的位置的, 1.配置文件中 <r ...

  4. FrieMonkey获取手机的IMSI等信息

    procedure THeaderFooterForm.FormCreate(Sender: TObject); var TelephonyManager: JTelephonyManager; Te ...

  5. RPG Maker MV游戏解包

    该文章最新版本请前往:https://www.crowsong.xyz/127.html 前言 使用Petschko's RPG-Maker-MV File-Decrypter进行解包 使用Petsc ...

  6. return view 详解 MVC

    1.return View(); 返回值 类型:System.Web.Mvc.ViewResult将视图呈现给响应的 View() 结果. 注释 View() 类的此方法重载将返回一个具有空 View ...

  7. Python装饰器和回调函数

    1.装饰器 装饰器用来实现一种切面功能,即一些函数在调用前都必须实现的功能,比如用户是否登录,用户是否有权限这类需求,都很容易由装饰器来实现. import functools def log(fun ...

  8. 302Java_前定义

    第零章 前定义 1 介绍 1.1 简介 Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承.指针等概念,因此Java语言具有功能强大和简单易用两个特征. ...

  9. nvm淘宝源升级安装最新稳定版nodejs

    为了在服务器上面升级nodejs,用nvm下载实在太慢了,推荐淘宝源安装命令,非常快能安装好: 第一步: NVM_NODEJS_ORG_MIRROR=https://npm.taobao.org/mi ...

  10. sentinel 核心概念

    编者注:前段时间笔者在团队内部分享了sentinel原理设计与实现,主要讲解了sentinel基础概念和工作原理,工作原理部分大家听了基本都了解了,但是对于sentinel的几个概念及其之间的关系还有 ...