2017-09-27 43 views
2

为aiohttp的入门文档给下面的客户端的例子:aiohttp:何时可以使用response.status?

async with aiohttp.ClientSession() as session: 
    async with session.get('https://api.github.com/events') as resp: 
     print(resp.status) 
     print(await resp.text()) 

我无法理解当response.status将可用。我的理解是,协程在await response.read()行释放控制权。在等待响应回复之前,我怎么可能访问状态?

+0

你不能。状态是响应标题,它不会“更新”。 –

+0

什么?在得到答复之前,您不具备*身份。 – jonrsharpe

+0

这就是我正在阅读的[这里](http://aiohttp.readthedocs.io/en/stable/client.html)。如果我不检查状态,我该如何处理失败代码? –

回答

3

重要的区别:如果等候的数据不avalible足够快await ...可以释放背景下的控制,例如。 async with ...声明也是如此。因此,您的代码只有在resp可用时才能达到print(resp.status)行。

例如代码:

import aiohttp 
import asyncio 
import urllib.parse 
import datetime 

async def get(session, url): 
    print("[{:%M:%S.%f}] getting {} ...".format(datetime.datetime.now(), urllib.parse.urlsplit(url).hostname)) 
    async with session.get(url) as resp: 
     print("[{:%M:%S.%f}] {}, status: {}".format(datetime.datetime.now(), urllib.parse.urlsplit(url).hostname, resp.status)) 
     doc = await resp.text() 
     print("[{:%M:%S.%f}] {}, len: {}".format(datetime.datetime.now(), urllib.parse.urlsplit(url).hostname, len(doc))) 

async def main(): 
    session = aiohttp.ClientSession() 

    url = "http://demo.borland.com/Testsite/stadyn_largepagewithimages.html" 
    f1 = asyncio.ensure_future(get(session, url)) 
    print("[{:%M:%S.%f}] added {} to event loop".format(datetime.datetime.now(), urllib.parse.urlsplit(url).hostname)) 

    url = "https://stackoverflow.com/questions/46445019/aiohttp-when-is-the-response-status-available" 
    f2 = asyncio.ensure_future(get(session, url)) 
    print("[{:%M:%S.%f}] added {} to event loop".format(datetime.datetime.now(), urllib.parse.urlsplit(url).hostname)) 

    url = "https://api.github.com/events" 
    f3 = asyncio.ensure_future(get(session, url)) 
    print("[{:%M:%S.%f}] added {} to event loop".format(datetime.datetime.now(), urllib.parse.urlsplit(url).hostname)) 

    await f1 
    await f2 
    await f3 

    session.close() 

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

可以产生这样的结果:

[16:42.415481] added demo.borland.com to event loop 
[16:42.415481] added stackoverflow.com to event loop 
[16:42.415481] added api.github.com to event loop 
[16:42.415481] getting demo.borland.com ... 
[16:42.422481] getting stackoverflow.com ... 
[16:42.682496] getting api.github.com ... 
[16:43.002515] demo.borland.com, status: 200 
[16:43.510544] stackoverflow.com, status: 200 
[16:43.759558] stackoverflow.com, len: 110650 
[16:43.883565] demo.borland.com, len: 239012 
[16:44.089577] api.github.com, status: 200 
[16:44.318590] api.github.com, len: 43055 

澄清(THX @deceze):在这里你可以看到(看括号之间的时间),所有的协同程序在发送检索网站的请求之后释放控件,并在等待响应文本的同时第二次释放控件。与stackoverflow相比,borland也有很多文本(排除了其他网络特征),尽管之前提出请求,但它只是在打印完stackoverflow文本之后才显示出来。

+0

*“Borland公司,而相比之下,计算器和github上发布第二次” * - 不,他们都“释放第二时间”;根据个人服务器的速度,网络条件和事件循环内的时间安排,下载和阅读正文的时间,只需按照您碰巧看到的响应顺序进行即可。 – deceze

+0

谢谢。所以如果我理解正确,'async with'在进入块之前等待'resp'协同程序。就像'await'等待'resp.text()' - 响应中的另一个协程 - 在继续以下语句之前。 –

+0

好了,'resp'是一个变量,'session.get()'是协程。但是你的想法是正确的,该线等待,直到它可以给'resp'赋值。 – user3608078

2

resp对象可用内部async with块。因此resp.status也可用。您还可以拨打await一些方法,如resp.text()但不会释放async with块的控制权。即使已调用await,也可以使用resp

3

你第一次得到的HTTP响应头,其中包括在第一线的状态代码。如果你这样选择,你可以阅读其余的响应主体(这里的resp.text())。由于标题总是相对较小并且身体可能非常大,所以aiohttp可让您有机会分别阅读这两个标题。