ayncio小结

2016-09-19  本文已影响167人  小博乐

异步IO模型需要一个消息循环,在消息循环中,主线程不断地重复“读取消息-处理消息”的过程:

loop = get_event_loop()
while True: 
    event = loop.get_event() 
    process_event(event)

实例:
用asyncio的一部网络来获取sina、sohu和163的网站首页:

import asyncio

@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() 
        #yield from asyncio.sleep(2)
        if line == b'\r\n': 
            break 
        print('%s header > %s' % (host, line.decode('utf-8').rstrip())) 
    # Ignore the body, close the socket 
    writer.close()

loop = asyncio.get_event_loop()
tasks = [wget(host) for host in ['www.sina.com.cn', 'www.sohu.com', 'www.163.com']]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()

执行结果如下:

wget www.sina.com.cn...
wget www.163.com...
wget www.sohu.com...
www.sina.com.cn
www.sina.com.cn header > HTTP/1.1 200 OK
www.sina.com.cn header > Server: nginx
www.sina.com.cn header > Date: Mon, 19 Sep 2016 03:03:30 GMT
www.sina.com.cn header > Content-Type: text/html
www.sina.com.cn header > Last-Modified: Mon, 19 Sep 2016 03:03:13 GMT
www.sina.com.cn header > Vary: Accept-Encoding
www.sina.com.cn header > Expires: Mon, 19 Sep 2016 03:04:30 GMT
www.sina.com.cn header > Cache-Control: max-age=60
www.sina.com.cn header > X-Powered-By: schi_v1.02
www.sina.com.cn header > Age: 52
www.sina.com.cn header > Content-Length: 593409
www.sina.com.cn header > X-Cache: HIT from localhost
www.sina.com.cn header > Connection: close
www.163.com
www.163.com header > HTTP/1.1 200 OK
www.163.com header > Expires: Mon, 19 Sep 2016 03:05:44 GMT
www.163.com header > Date: Mon, 19 Sep 2016 03:04:24 GMT
www.163.com header > Server: nginx
www.163.com header > Content-Type: text/html; charset=GBK
www.163.com header > Vary: Accept-Encoding,User-Agent,Accept
www.163.com header > Cache-Control: max-age=80
www.163.com header > X-Via: 1.1 czdx87:4 (Cdn Cache Server V2.0), 1.1 jifang134:10 (Cdn Cache Server V2.0)
www.163.com header > Connection: close
www.sohu.com
www.sohu.com header > HTTP/1.1 200 OK
www.sohu.com header > Content-Type: text/html
www.sohu.com header > Content-Length: 92145
www.sohu.com header > Connection: close
www.sohu.com header > Date: Mon, 19 Sep 2016 03:02:52 GMT

www.sohu.com header > Server: SWS
www.sohu.com header > Vary: Accept-Encoding
www.sohu.com header > Cache-Control: no-transform, max-age=120
www.sohu.com header > Expires: Mon, 19 Sep 2016 03:04:52 GMT
www.sohu.com header > Last-Modified: Mon, 19 Sep 2016 03:02:45 GMT
www.sohu.com header > Content-Encoding: gzip
www.sohu.com header > X-RS: 17799606.26974656.25737794
www.sohu.com header > FSS-Cache: HIT from 5397379.8739725.6791606
www.sohu.com header > FSS-Proxy: Powered by 3496806.4938608.4891004

在上述执行结果中,按照正常的异步IO的逻辑,打印出header的host不应该连续,但实际上,出现这种结果的原因是因为line = yield from reader.readline() 的执行时间非常短,还没有等到线程去执行其他任务的时候就已经执行完毕,所以就出现了连续打印的结果。(个人理解)
比如将上述注释掉的yield from asyncio.sleep(2)还原回来,则执行结果就变成了如下结果:

wget www.sina.com.cn...
wget www.163.com...
wget www.sohu.com...
www.sina.com.cn
www.163.com

www.sohu.com
www.sina.com.cn header > HTTP/1.1 200 OK
www.sohu.com header > HTTP/1.1 200 OK
www.sina.com.cn header > Server: nginx
www.sohu.com header > Content-Type: text/html
www.163.com header > HTTP/1.1 200 OK
www.sina.com.cn header > Date: Mon, 19 Sep 2016 03:07:54 GMT
www.sohu.com header > Content-Length: 92072
www.163.com header > Date: Mon, 19 Sep 2016 03:08:56 GMT
www.sina.com.cn header > Content-Type: text/html
www.sohu.com header > Connection: close
www.163.com header > Server: openresty
www.sina.com.cn header > Last-Modified: Mon, 19 Sep 2016 03:06:45 GMT
www.sohu.com header > Date: Mon, 19 Sep 2016 03:05:22 GMT
www.163.com header > Content-Type: text/html; charset=GBK
www.sina.com.cn header > Vary: Accept-Encoding

拓展

def g(x):
... yield from range(x, 0, -1)
... yield from range(x)
...
list(g(5))
[5, 4, 3, 2, 1, 0, 1, 2, 3, 4]

也就是说yield from是可以将generator串联的。

上一篇 下一篇

猜你喜欢

热点阅读