python2中的gevent通过协程已经实现了异步IO,python3中专门有一个模块来处理异步IO,ascyio模块。
先看一个列子:
import asyncio
import datetime
import time
@asyncio.coroutine
def hello():
print('任务一 开始了!')
print('执行中')
print('遇到了费时操作')
r = yield from asyncio.sleep(5)
print(str(r))
print('任务一 费事操作做完了')
print('任务一继续')
@asyncio.coroutine
def hello2():
print('任务二 开始了!')
print('执行中')
print('遇到了费时操作')
r = yield from asyncio.sleep(5)
print('任务二费事操作做完了')
print('任务二继续')
start=datetime.datetime.now()
loop=asyncio.get_event_loop()
task = [hello(),hello2()]
loop.run_until_complete(asyncio.wait(task))
loop.close()
print(datetime.datetime.now()-start)
运行结果:
任务二 开始了!
执行中
遇到了费时操作
任务一 开始了!
执行中
遇到了费时操作
任务二费事操作做完了
任务二继续
None
任务一 费事操作做完了
任务一继续
0:00:05.003013
从运行结果看,效果和gevent是一样的,即遇到费时操作直接跳到另一个协程里,直到io结束跳回来。
具体实现步骤:
- 用@asyncio.coroutine将一个生成器函数变为corutine对象
- yield from 表示等待一个费时操作返回结果
- 创建loop,将任务添加进去
- 运行loop
实际问题中并不会出现sleep这样的费时,async中也封装了各种的io操作,使其支持协程。
下面是对网络io的例子:
``` stylus
import asyncio
@asyncio.coroutine
def get_hearder(url):
print('正在连接%s'%url)
connect = asyncio.open_connection(url,80)
print('connect is %s'%connect)
reader,writer = yield from connect
header = 'GET / HTTP/1.0\r\nHost: %s\r\n\r\n' %url
writer.write(header.encode('utf8'))
print('正在发送请求')
yield from writer.drain()#冲洗缓存区,不知道啥意思,大概是发送请求把,请指正
while True:
print('正在获取数据%s'%url)
line = yield from reader.readline()
if line == b'\r\n':
break
print('%s header > %s' % (url, line.decode('utf-8').rstrip()))
writer.close()#关闭连接
loop = asyncio.get_event_loop()
tasks = [ get_hearder(url) for url in (
'www.baidu.com',
'www.souhu.com',
'www.soso.com', # asyncio.open_connection的参数为host,不需要加http
)]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
运行结果:
``` stylus
正在连接www.souhu.com
connect is <generator object open_connection at 0x000001B45A1E94C0>
正在连接www.baidu.com
connect is <generator object open_connection at 0x000001B45A1E9620>
正在连接www.soso.com
connect is <generator object open_connection at 0x000001B45A1E97D8>
正在发送请求
正在获取数据www.baidu.com
www.baidu.com header > HTTP/1.1 200 OK
正在获取数据www.baidu.com
www.baidu.com header > Date: Fri, 21 Jul 2017 06:23:40 GMT
正在获取数据www.baidu.com
www.baidu.com header > Content-Type: text/html
正在获取数据www.baidu.com
www.baidu.com header > Content-Length: 14613
正在获取数据www.baidu.com
www.baidu.com header > Last-Modified: Wed, 28 Jun 2017 02:16:00 GMT
正在获取数据www.baidu.com
www.baidu.com header > Connection: Close
正在获取数据www.baidu.com
www.baidu.com header > Vary: Accept-Encoding
正在获取数据www.baidu.com
www.baidu.com header > Set-Cookie: BAIDUID=B275DA6992F2400B0505F9244F6FD742:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
正在获取数据www.baidu.com
www.baidu.com header > Set-Cookie: BIDUPSID=B275DA6992F2400B0505F9244F6FD742; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
正在获取数据www.baidu.com
www.baidu.com header > Set-Cookie: PSTM=1500618220; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
正在获取数据www.baidu.com
www.baidu.com header > P3P: CP=" OTI DSP COR IVA OUR IND COM "
正在获取数据www.baidu.com
www.baidu.com header > Server: BWS/1.1
正在获取数据www.baidu.com
www.baidu.com header > X-UA-Compatible: IE=Edge,chrome=1
正在获取数据www.baidu.com
www.baidu.com header > Pragma: no-cache
正在获取数据www.baidu.com
www.baidu.com header > Cache-control: no-cache
正在获取数据www.baidu.com
www.baidu.com header > Accept-Ranges: bytes
正在获取数据www.baidu.com
正在发送请求
正在获取数据www.soso.com
www.soso.com header > HTTP/1.1 302 Moved Temporarily
正在获取数据www.soso.com
www.soso.com header > Server: nginx
正在获取数据www.soso.com
www.soso.com header > Date: Fri, 21 Jul 2017 06:23:40 GMT
正在获取数据www.soso.com
www.soso.com header > Content-Type: text/html
正在获取数据www.soso.com
www.soso.com header > Content-Length: 154
正在获取数据www.soso.com
www.soso.com header > Connection: close
正在获取数据www.soso.com
www.soso.com header > Location: http://www.sogou.com/?rfrom=soso
正在获取数据www.soso.com
www.soso.com header > Expires: Fri, 21 Jul 2017 06:23:40 GMT
正在获取数据www.soso.com
www.soso.com header > Cache-Control: max-age=0
正在获取数据www.soso.com
正在发送请求
正在获取数据www.souhu.com
www.souhu.com header > HTTP/1.1 301 Moved Permanently
正在获取数据www.souhu.com
www.souhu.com header > Server: Tengine/1.4.2
正在获取数据www.souhu.com
www.souhu.com header > Date: Fri, 21 Jul 2017 06:23:39 GMT
正在获取数据www.souhu.com
www.souhu.com header > Content-Type: text/html
正在获取数据www.souhu.com
www.souhu.com header > Content-Length: 286
正在获取数据www.souhu.com
www.souhu.com header > Connection: close
正在获取数据www.souhu.com
www.souhu.com header > Location: http://127.0.0.1/
正在获取数据www.souhu.com
运行结果里,貌似asycio只把连接当成了费时操作,其他部分都同步了,不知是不是时间太短而忽略掉了,或者是有特殊的调度方法。
总结
async封装了异步io操作,使用它可以方便的用单线程的协程方式实现异步io