这是一种pythonic方法,可以使代码同时用于常规函数和异步协程吗?

2024-06-01 05:22:33 发布

您现在位置:Python中文网/ 问答频道 /正文

下面是一个请求处理函数。处理请求意味着根据请求类型调用普通函数或协程。你知道吗

目前,我有两个非常相似的代码块,它们只在函数调用(常规调用或异步等待)上有所不同。你知道吗

try:
   # either:
   result = func()
   # or:
   result = await func()
except RequestError:
   # send error reply (few lines of code)
except Exception:
   # send message about unexpected failure (few lines of code)
else:
   # send the result (also few lines of code)

当然,我开始想,我怎么能只写一次代码(干的)。你知道吗

我可以写三个小助手(reply_errorreply_failurereply_result)或者一个更大的助手reply(result, exception)。这是一个临时的解决方案,并没有大的改进。甚至可能在代码可读性方面后退一步。你知道吗

或者我也可以从一个异步任务中调用一个常规函数func,但是创建一个任务而不做任何异步操作的开销是不合理的。你知道吗

不过,我可以自己运行这种特殊情况(“降级”)协同程序,下面是一个概念证明:

async def test():
    # not really asynchronous
    print("hello")
    return 123 

def call_coro(coro):
    try:
        coro.send(None)
    except StopIteration as err:
        return err.args[0]
    raise RuntimeError("not special case coro")

print(call_coro(test()))

结果将是(未经测试):

async def handle_request(func, is_async):
    try:
        if is_async:
            result = await func()
        else:
            result = func()
    except ..... # error handling as above

以及用法:

is_async = asyncio.iscoroutinefunction(func)
if is_async:
    # create_task == ensure_future in Python < 3.7
    asyncio.create_task(handle_request(func, True))
else:
    call_coro(handle_request(func, False))

这就是我迄今为止所尝试的,也是我正在考虑的替换当前代码的方法。它是Python的还是相反的?你知道吗


Tags: of代码sendasynciscodeerrorresult