异步IO的出现源自于CPU速度与IO速度完全不匹配

一般的可以采用多线程或者多进程的方式来解决IO等待的问题

同样异步IO也可以解决同步IO所带来的问题

常见的异步IO的实现方式是使用一个消息循环, 主线程不断的读取这个消息循环以便确定IO操作是否完成

1 协程

  协程(微线程, 纤程)

  一般子程序调用是一个入口一个出口, 调用的顺序也是明确的

  但是协程不同, 执行过程中子程序内部中断, 就会转而执行别的子程序, 等待合适的时间返回 , 这样的行为类似于进程的切换

  正因为协程又类似于线程执行的特性, 但是子程序切换几乎没有切换开销, 因此性能很好

  而且协程还可以避免临界资源操作的问题

  协程是一个线程执行

  构造协程一般是使用生成器, 利用send()发送相互传递数据

  常见的生产者消费者的范例

def consumer():
r = ''
while True:
n = yield r
if not n:
return
print('[CONSUMER] Consuming %s...' % n)
r = '200 OK' def produce(c):
c.send(None)
n = 0
while n < 5:
n = n + 1
print('[PRODUCER] Producing %s...' % n)
r = c.send(n)
print('[PRODUCER] Consumer return: %s' % r)
c.close() c = consumer()
produce(c)

2 asyncio

  基本使用为

import asyncio

@asyncio.coroutine
def hello():
print("Hello world!")
# 异步调用asyncio.sleep(1):
r = yield from asyncio.sleep(1)
print("Hello again!") # 获取EventLoop:
loop = asyncio.get_event_loop()
# 执行coroutine
loop.run_until_complete(hello())
loop.close()

  使用装饰器asyncio.coroutine装饰一个执行函数, 这样便可以生成一个异步执行IO的函数

  使用asyncio.get_event_loop()创建一个循环

  通过这个循环的对象执行run_until_complete()来执行异步IO

    其中run_until_complete()可以传入一个函数执行

    如果需要多个函数的话, 就需要将这些函数执行方法一个list中, 并使用asyncid.wait(list)

tasks = [hello(), hello()]
loop.run_until_complete(asyncio.wait(tasks))

  最后调用close()结束异步IO

  其中函数的写法是 需要使用 yield from来实现异步IO

  获取网页的函数编写如下

@asyncio.coroutine
def wget(host):
print('wget %s...' % host)
connect = asyncio.open_connection(host, 80)
reader, writer = yield from connect
header = 'GET / HTTP/1.0\r\nHost: %s\r\n\r\n' % host
writer.write(header.encode('utf-8'))
yield from writer.drain()
while True:
line = yield from reader.readline()
if line == b'\r\n':
break
print('%s header > %s' % (host, line.decode('utf-8').rstrip()))
writer.close()

3 async和await

  使用asyncio.coroutine可以吧一个生成器标记为coroutine类型

  然后在内部使用yield from调用另一个coroutine实现异步操作

  为了进一步简化操作, 出现了async和await, 这是在python3.5开始支持的语法

  简化如下

    1) 装饰器asyncio.corontine替换为async

    2) yield from替换为await

  因此上述代码可以简化为

async def hello():
print("Hello world!")
r = await asyncio.sleep(1)
print("Hello again!") async def wget(host):
print('wget %s...' % host)
connect = asyncio.open_connection(host, 80)
reader, writer = await connect
header = 'GET / HTTP/1.0\r\nHost: %s\r\n\r\n' % host
writer.write(header.encode('utf-8'))
await writer.drain()
while True:
line = await reader.readline()
if line == b'\r\n':
break
print('%s header > %s' % (host, line.decode('utf-8').rstrip()))
writer.close()

4 aiohttp

  asyncio实现了单线程并发io操作, 如果只是应用于客户端, 那么作用还不是那么明显

  针对于服务器, asyncio可能发挥更好的效果, 基于http协议实现的asyncio就是aiohttp

  安装

pip install aiohttp

  1) 导入包

import asyncio
from aiohttp import web

  2) 实现mian代码

if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(init(loop))
loop.run_forever()

  3) 编写初始化函数

  将循环loop作为参数传入, 用于创建webapp

  添加路由, 并指定处理函数

  最后创建服务器, 利用create_server()创建TCP服务

async def init(loop):
app = web.Application(loop=loop)
app.router.add_route('GET', '/', index)
app.router.add_route('GET', '/hello/{name}', hello)
srv = await loop.create_server(app.make_handler(), '127.0.0.1', 8000)
print('Server started at http://127.0.0.1:8000...')
return srv

  4) 编写两个路由的处理函数

async def index(request):
await asyncio.sleep(0.5)
return web.Response(body=b'<h1>Index</h1>') async def hello(request):
await asyncio.sleep(0.5)
text = '<h1>hello, %s!</h1>' % request.match_info['name']
return web.Response(body=text.encode('utf-8'))

  

第十七章-异步IO的更多相关文章

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

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

  2. JS读书心得:《JavaScript框架设计》——第12章 异步处理

    一.何为异步   执行任务的过程可以被分为发起和执行两个部分. 同步执行模式:任务发起后必须等待直到任务执行完成并返回结果后,才会执行下一个任务. 异步执行模式:任务发起后不等待任务执行完成,而是马上 ...

  3. 《深入浅出Node.js》第3章 异步I/O

    @by Ruth92(转载请注明出处) 第3章 异步I/O Node 的基调:异步 I/O.事件驱动.单线程. Node 不再是一个服务器,而是一个可以基于它构建各种高速.可伸缩网络应用的平台. No ...

  4. node.js零基础详细教程(4):node.js事件机制、node异步IO操作

    第四章 建议学习时间3小时  课程共10章 学习方式:详细阅读,并手动实现相关代码 学习目标:此教程将教会大家 安装Node.搭建服务器.express.mysql.mongodb.编写后台业务逻辑. ...

  5. 流畅python学习笔记:第十七章:并发处理

    第十七章:并发处理 本章主要讨论Python3引入的concurrent.futures模块.在python2.7中需要用pip install futures来安装.concurrent.futur ...

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

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

  7. 简述同步IO、异步IO、阻塞IO、非阻塞IO之间的联系与区别

    POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...

  8. 同步IO、异步IO、阻塞IO、非阻塞IO之间的联系与区别

    POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...

  9. python -- 异步IO 协程

    python 3.4 >>> import asyncio >>> from datetime import datetime >>> @asyn ...

随机推荐

  1. iPhone缓存网络数据

    本文转载至 http://blog.csdn.net/wwang196988/article/details/7542918   在iPhone应用程序中,我们经常要用去网络下载一些文件,比如xml, ...

  2. 怎样查看电脑登录过的wifi密码?

    https://jingyan.baidu.com/album/fcb5aff770f7e6edaa4a71d9.html?picindex=7

  3. greenlet和gevent模块的区别?

    协程是一中多任务实现方式,它不需要多个进程或线程就可以实现多任务. yield能实现协程,不过实现过程不易于理解,greenlet是在这方面做了改进,通过switch. greenlet可以实现协程, ...

  4. 我的Android进阶之旅------>如何将Android源码导入Eclipse中来查看(非常实用)

    Android源码下载完成的目录结构如如所示: step1:将.classpath文件拷贝到源代码的根目录 Android源码支持多种IDE,如果是针对APP层做开发的话,建议大家使用Eclipse开 ...

  5. python cookbook第三版学习笔记十七:委托属性

    我们想在访问实例的属性时能够将其委托到一个内部持有的对象上,这经常用到代理机制上 class A:     def spam(self,x):         print("class_A: ...

  6. IOS NSDate 调整当前时间戳为明天

    这个可以根据需要调整 在day  month  hour minute second  等都行 以下是以当前时间戳为基础,调整时间为明天的零点零时零分零秒  可以根据需要 写成毫秒的 +(NSStri ...

  7. HTTP基础概念讲解

    HTTP基础概念讲解 作者:Danbo 时间:2016-03-17 1.1.http协议头部:curl -I www.meituan.com 1.2.静态和动态 静态网页:纯HTML格式的网页,后台没 ...

  8. python学习笔记20160413

    1. type(val) #查看val的类型. 2. 出现错误的时候, 读懂错误信息.3. raw_input('xxx') #读取用户输入都是string类型数据.4. ValueError: in ...

  9. Linux 上通过rpm安装mysql

    安装mysql之前要remove掉系统自带的mysql: rpm -qa | grep "MySQL*"    和rpm -qa | grep mysql  要确保卸载干净 rpm ...

  10. Linux电源管理(4)-Power Manager Interface【转】

    本文转载自:http://www.wowotech.net/pm_subsystem/pm_interface.html 1. 前言 Linux电源管理中,相当多的部分是在处理Hibernate.Su ...