【发布时间】:2019-01-15 18:39:06
【问题描述】:
我有几个速率限制器类(一个未显示),我想为其创建一个 ABC。 request 方法是一个异步上下文管理器。使用下面显示的代码,我得到
“请求”的签名与超类型“RateLimiterInterface”不兼容
如果我尝试用@asynccontextmanager 来装饰抽象方法,我会收到输入错误:
“asynccontextmanager”的参数 1 具有不兼容的类型“Callable[[RateLimiterInterface], Coroutine[Any, Any, AsyncIterator[Any]]]”;预期“可调用[...,AsyncIterator[]]”
我该怎么做?
class RateLimiterInterface(abc.ABC):
@abc.abstractmethod
async def request(self) -> AsyncIterator:
pass
class LeakyBucketRateLimiter(RateLimiterInterface):
def __init__(self, max_tokens: Optional[int] = None, rate: float = 60) -> None:
self.max_tokens = max_tokens
self.rate = rate
self._bucket = max_tokens
self._last_added_at = time.time()
@contextlib.asynccontextmanager
async def request(self) -> AsyncIterator:
if self._bucket is None:
yield
return
while not self._bucket:
await asyncio.sleep(0)
self._add_tokens(int((time.time() - self._last_added_at) * self.rate))
self._bucket -= 1
yield
return
def _add_tokens(self, num_tokens: int) -> None:
if num_tokens == 0:
return
self._bucket += num_tokens
if self._bucket > self.max_tokens:
self._bucket = self.max_tokens
self._last_added_at = time.time()
【问题讨论】:
-
您是否尝试过在您的 ABC 中使用
contextlib.asynccontextmanager装饰器? -
是的,我确实尝试将
@contextlib.asynccontextmanager作为第二个装饰器添加到我的 ABC 中的抽象请求方法中。那是我收到上面提到的打字错误的时候。 -
请看这个答案stackoverflow.com/a/68911014/4088675。本质上,您需要从 abstractmethod 声明中删除“async”关键字
标签: python python-3.x python-asyncio mypy