首页 > 解决方案 > 使用 aiohttp 时如何获取 response_time 和 response_size

问题描述

是否可以获得使用 aiohttp 发出的每个请求的响应时间和响应大小?

该文档似乎在任何地方都没有这些属性。

谢谢

标签: pythonpython-3.xpython-asyncioaiohttp

解决方案


len(response.text())将返回解压缩响应的大小。如果您想要原始压缩响应的大小,您需要auto_decompress=False在创建aiohttp.ClientSession. 之后,您可以使用len(await response.read()). 但它会变得不response.text()可用,因为它需要未压缩的响应。要使其再次可用,您必须手动解压缩:

import time
import zlib
import brotli

async with aiohttp.ClientSession(auto_decompress=False) as session:
    start = time.monotonic()
    response = await session.get(url='www.test.com')
    response_time = time.monotonic() - start
    response_size = len(await response.read())

    encoding = response.headers['Content-Encoding']
    if encoding == 'gzip':
        response._body = zlib.decompress(response._body, 16 + zlib.MAX_WBITS)
    elif encoding == 'deflate':
        response._body = zlib.decompress(response._body, -zlib.MAX_WBITS)
    elif encoding == 'br':
        response._body == brotli.decompress(response._body)

    response_text = await response.text()

关于time.time()来自pymotw.com

因为time.time()查看系统时钟,并且系统时钟可以由用户或系统服务更改以在多台计算机之间同步时钟,time.time()所以重复调用可能会产生向前和向后的值。当尝试测量持续时间或以其他方式使用这些时间进行计算时,这可能会导致意外行为。通过 using 避免这些情况time.monotonic(),它总是返回向前的值。

aiohttp 文档建议使用loop.time()(这也是单调的):

async def on_request_start(session, trace_config_ctx, params):
    trace_config_ctx.start = asyncio.get_event_loop().time()

async def on_request_end(session, trace_config_ctx, params):
    elapsed = asyncio.get_event_loop().time() - trace_config_ctx.start
    print("Request took {}".format(elapsed))

trace_config = aiohttp.TraceConfig()
trace_config.on_request_start.append(on_request_start)
trace_config.on_request_end.append(on_request_end)
async with aiohttp.ClientSession(trace_configs=[trace_config]) as client:
    client.get('http://example.com/some/redirect/')

推荐阅读