python3中異步IO

python2中的gevent通過協(xié)程已經(jīng)實(shí)現(xiàn)了異步IO,python3中專門有一個(gè)模塊來處理異步IO,ascyio模塊。

先看一個(gè)列子:

import asyncio
import datetime
import time


@asyncio.coroutine
def hello():
    print('任務(wù)一 開始了!')
    print('執(zhí)行中')
    print('遇到了費(fèi)時(shí)操作')
    r = yield from asyncio.sleep(5)
    print(str(r))
    print('任務(wù)一 費(fèi)事操作做完了')
    print('任務(wù)一繼續(xù)')
@asyncio.coroutine
def hello2():
    print('任務(wù)二 開始了!')
    print('執(zhí)行中')
    print('遇到了費(fèi)時(shí)操作')
    r = yield from asyncio.sleep(5)
    print('任務(wù)二費(fèi)事操作做完了')
    print('任務(wù)二繼續(xù)')
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)

運(yùn)行結(jié)果:

任務(wù)二 開始了!
執(zhí)行中
遇到了費(fèi)時(shí)操作
任務(wù)一 開始了!
執(zhí)行中
遇到了費(fèi)時(shí)操作
任務(wù)二費(fèi)事操作做完了
任務(wù)二繼續(xù)
None
任務(wù)一 費(fèi)事操作做完了
任務(wù)一繼續(xù)
0:00:05.003013

從運(yùn)行結(jié)果看,效果和gevent是一樣的,即遇到費(fèi)時(shí)操作直接跳到另一個(gè)協(xié)程里,直到io結(jié)束跳回來。

具體實(shí)現(xiàn)步驟:

  1. 用@asyncio.coroutine將一個(gè)生成器函數(shù)變?yōu)閏orutine對(duì)象
  2. yield from 表示等待一個(gè)費(fèi)時(shí)操作返回結(jié)果
  3. 創(chuàng)建loop,將任務(wù)添加進(jìn)去
  4. 運(yùn)行l(wèi)oop

實(shí)際問題中并不會(huì)出現(xiàn)sleep這樣的費(fèi)時(shí),async中也封裝了各種的io操作,使其支持協(xié)程。
下面是對(duì)網(wǎng)絡(luò)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('正在發(fā)送請(qǐng)求')
yield from writer.drain()#沖洗緩存區(qū),不知道啥意思,大概是發(fā)送請(qǐng)求把,請(qǐng)指正
while True:
print('正在獲取數(shù)據(jù)%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()#關(guān)閉連接

loop = asyncio.get_event_loop()
tasks = [ get_hearder(url) for url in (
'www.baidu.com',
'www.souhu.com',
'www.soso.com', # asyncio.open_connection的參數(shù)為host,不需要加http

)]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()

運(yùn)行結(jié)果:

``` 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>
正在發(fā)送請(qǐng)求
正在獲取數(shù)據(jù)www.baidu.com
www.baidu.com header > HTTP/1.1 200 OK
正在獲取數(shù)據(jù)www.baidu.com
www.baidu.com header > Date: Fri, 21 Jul 2017 06:23:40 GMT
正在獲取數(shù)據(jù)www.baidu.com
www.baidu.com header > Content-Type: text/html
正在獲取數(shù)據(jù)www.baidu.com
www.baidu.com header > Content-Length: 14613
正在獲取數(shù)據(jù)www.baidu.com
www.baidu.com header > Last-Modified: Wed, 28 Jun 2017 02:16:00 GMT
正在獲取數(shù)據(jù)www.baidu.com
www.baidu.com header > Connection: Close
正在獲取數(shù)據(jù)www.baidu.com
www.baidu.com header > Vary: Accept-Encoding
正在獲取數(shù)據(jù)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
正在獲取數(shù)據(jù)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
正在獲取數(shù)據(jù)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
正在獲取數(shù)據(jù)www.baidu.com
www.baidu.com header > P3P: CP=" OTI DSP COR IVA OUR IND COM "
正在獲取數(shù)據(jù)www.baidu.com
www.baidu.com header > Server: BWS/1.1
正在獲取數(shù)據(jù)www.baidu.com
www.baidu.com header > X-UA-Compatible: IE=Edge,chrome=1
正在獲取數(shù)據(jù)www.baidu.com
www.baidu.com header > Pragma: no-cache
正在獲取數(shù)據(jù)www.baidu.com
www.baidu.com header > Cache-control: no-cache
正在獲取數(shù)據(jù)www.baidu.com
www.baidu.com header > Accept-Ranges: bytes
正在獲取數(shù)據(jù)www.baidu.com
正在發(fā)送請(qǐng)求
正在獲取數(shù)據(jù)www.soso.com
www.soso.com header > HTTP/1.1 302 Moved Temporarily
正在獲取數(shù)據(jù)www.soso.com
www.soso.com header > Server: nginx
正在獲取數(shù)據(jù)www.soso.com
www.soso.com header > Date: Fri, 21 Jul 2017 06:23:40 GMT
正在獲取數(shù)據(jù)www.soso.com
www.soso.com header > Content-Type: text/html
正在獲取數(shù)據(jù)www.soso.com
www.soso.com header > Content-Length: 154
正在獲取數(shù)據(jù)www.soso.com
www.soso.com header > Connection: close
正在獲取數(shù)據(jù)www.soso.com
www.soso.com header > Location: http://www.sogou.com/?rfrom=soso
正在獲取數(shù)據(jù)www.soso.com
www.soso.com header > Expires: Fri, 21 Jul 2017 06:23:40 GMT
正在獲取數(shù)據(jù)www.soso.com
www.soso.com header > Cache-Control: max-age=0
正在獲取數(shù)據(jù)www.soso.com
正在發(fā)送請(qǐng)求
正在獲取數(shù)據(jù)www.souhu.com
www.souhu.com header > HTTP/1.1 301 Moved Permanently
正在獲取數(shù)據(jù)www.souhu.com
www.souhu.com header > Server: Tengine/1.4.2
正在獲取數(shù)據(jù)www.souhu.com
www.souhu.com header > Date: Fri, 21 Jul 2017 06:23:39 GMT
正在獲取數(shù)據(jù)www.souhu.com
www.souhu.com header > Content-Type: text/html
正在獲取數(shù)據(jù)www.souhu.com
www.souhu.com header > Content-Length: 286
正在獲取數(shù)據(jù)www.souhu.com
www.souhu.com header > Connection: close
正在獲取數(shù)據(jù)www.souhu.com
www.souhu.com header > Location: http://127.0.0.1/
正在獲取數(shù)據(jù)www.souhu.com

運(yùn)行結(jié)果里,貌似asycio只把連接當(dāng)成了費(fèi)時(shí)操作,其他部分都同步了,不知是不是時(shí)間太短而忽略掉了,或者是有特殊的調(diào)度方法。

總結(jié)

async封裝了異步io操作,使用它可以方便的用單線程的協(xié)程方式實(shí)現(xiàn)異步io

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容