FengLiuFeseliud / pycloudmusic

优雅的异步高性能 Python 音乐 API 库 (网易云音乐)
https://fengliufeseliud.github.io/pycloudmusic/
MIT License
25 stars 4 forks source link

关于「返回代码」处理的建议 #1

Closed danzou1ge6 closed 2 years ago

danzou1ge6 commented 2 years ago

pycloudmusic 中经常出现如下模式:

class SomeApi:
    ...

    async def some_method(self, ...) -> Union[Generator[T, None, None], dict[str, Any]]:

        data = await _post("/api/...", {...})

        if data["code"] != 200:
            return data["code"]

        return (T(d) for d in data['something'])

    ...

这种模式导致在调用该方法时对于异常「返回代码」的处理非常繁琐:

x: SomeApi = ...
ret = await x.some_method(...)
if isinstance(ret, Generator):
    # 说明操作成功
    ...
else:
    # 说明操作失败
    ...

因此,我建议使用 Exception 来解决这个问题

class Music163BadCode(Exception):
    """当服务器返回代码 `code` 不为 200 时抛出"""
    def __init__(self, data: dict[str, Any]) -> None:
        self.data = data
    def __str__(self) -> str:
        return f'Music163BadCode({self.data["code"]}): {self.data}'

# `ahttp.py` 中的 `_post`
async def _post(
    path: str, 
    data: Optional[dict[str, Any]] = None
) -> dict[str, Any]:
    """post 请求 api 路径"""
    ret = await _post_url(f"https://music.163.com{path}", data)

    if ret['code'] != 200:
        raise Music163BadCode(ret)

    return ret

这样可以消除大量出现的 if ret['code'] != 200 语句,同时使操作失败的处理变得简洁

x: SomeApi = ...
try:
    ret = await x.some_method(...)
except Music163BadCode as err:
    # 操作失败
    ...
# 操作成功
...
FengLiuFeseliud commented 2 years ago

可以,v0.1.4 中更新