我正在尝试为aiohttp
编写一个 Package 器来检测慢速查询。
这是我的装饰:
import time
def report_slow_call(seconds=1.0):
def decorator(func):
async def wrapper(*args, **kwargs):
start_ts = time.perf_counter()
result = await func(*args, **kwargs)
elapsed = time.perf_counter() - start_ts
url = args[0] if args else kwargs.get('url')
if elapsed > seconds:
print(f"Slow call to: {url} ({elapsed:.2f} seconds).")
return result
return wrapper
return decorator
我给客户端对象get
函数打了个补丁,它工作得很好(在ipython
中执行):
In [2]: import aiohttp
...: http_client = aiohttp.ClientSession()
...: http_client.get = report_slow_call(seconds=0.03)(http_client.get)
...: await http_client.get("http://stackoveflow.com")
Slow call to: http://stackoveflow.com (0.11 seconds).
Out[2]:
<ClientResponse(http://stackoveflow.com) [200 OK]>
<CIMultiDictProxy('accept-ch': 'Sec-CH-UA, Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version, Sec-CH-UA-Mobile', 'Cache-Control': 'max-age=0, private, must-revalidate', 'Connection': 'close', 'Content-Length': '477', 'Content-Type': 'text/html; charset=utf-8', 'Date': 'Mon, 17 Apr 2023 15:42:50 GMT', 'Server': 'nginx', 'Set-Cookie': 'sid=82900a62-dd36-11ed-85ae-a4d3e99a9525; path=/; domain=.stackoveflow.com; expires=Sat, 05 May 2091 18:56:57 GMT; max-age=2147483647; HttpOnly')>
**问题:**当我尝试通过上下文管理器运行它时,我得到以下错误:
In [4]: async with http_client.get("http://stackoveflow.com", raise_for_status=True) as response:
...: print(response)
...:
<ipython-input-4-fd5ea6565740>:1: RuntimeWarning: coroutine 'report_slow_call.<locals>.decorator.<locals>.wrapper' was never awaited
async with http_client.get("http://stackoveflow.com", raise_for_status=True) as response:
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[4], line 1
----> 1 async with http_client.get("http://stackoveflow.com", raise_for_status=True) as response:
2 print(response)
TypeError: 'coroutine' object does not support the asynchronous context manager protocol
你们谁能提出一个正确实施的想法,好吗?
1条答案
按热度按时间ctzwtxfj1#
我检查了
httpaio
的源代码,了解了函数是如何执行的。所以,我没有修补
ClientSession.get
,而是修补了ClientSession._request
,装饰器现在工作得很好。解决方案