Open xiyihan0 opened 10 months ago
一个可能的解决方案是定义一个装饰器:
def retry_on_error(func):
def wrapper(*args, **kwargs):
import time
while True:
result = func(*args, **kwargs)
if 'error' not in result:
return result
print('Error detected:%s'%result['error'])
if result['error']['message'] == 'Rate Limit': #retry
print('Rate Limit, wait for 8s to try again')
time.sleep(8)
else:
raise PixivError('Error detected:%s'%result['error'])
return wrapper
然后将其应用到aapi中的方法上:
@retry_on_error
def novel_comments(
self,
novel_id: int | str,
offset: int | str | None = None,
include_total_comments: str | bool | None = None,
req_auth: bool = True,
) -> ParsedJson:
...
装饰器确实是个很好的思路,能节省很多应用层error的判断的时间。
retry可以再考虑下,有时rate limit不一定要当前线程time.sleep(8)
,比如在集群内换个新的token/proxy
因此建议:
@raise_on_error
def xxx_api(...)
class RateLimitError(Exception):
pass
def retry_on_error(func):
# 对 message 这类明确的如`Rate Limit`,抛异常让外部去决定如何处理
raise RateLimitError()
一个是当api调用频率过高时,会返回:
{'error': {'user_message': '', 'message': 'Rate Limit', 'reason': '', 'user_message_details': {}}}
另一个是当api访问到一些不存在的资源(如被删除的用户页面或小说)时,会返回:
{'error': {'user_message': 'Your access is currently restricted.', 'message': '', 'reason': '', 'user_message_details': {}}}
例如:这两种错误均以结果直接返回,并没有引发PixivError异常。