Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

使用api过程遇到的2个以结果返回的错误 #327

Open
xiyihan0 opened this issue Jan 15, 2024 · 2 comments
Open

使用api过程遇到的2个以结果返回的错误 #327

xiyihan0 opened this issue Jan 15, 2024 · 2 comments

Comments

@xiyihan0
Copy link
Contributor

一个是当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': {}}}
例如:

api = AppPixivAPI()
api.set_auth(...)
print(api.user_detail(52714160))

这两种错误均以结果直接返回,并没有引发PixivError异常。

@xiyihan0
Copy link
Contributor Author

一个可能的解决方案是定义一个装饰器:

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:
    ...

@upbit
Copy link
Owner

upbit commented Jan 15, 2024

装饰器确实是个很好的思路,能节省很多应用层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()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants