下面是请求处理功能。处理请求意味着根据请求类型调用普通函数或协程。
当前,我有两个非常相似的代码块,它们的区别仅在于函数调用(常规调用或异步等待)上。
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)
自然地,我开始怀疑,如何只写一次代码(DRY)。
我可以写三个小助手(reply_error
,reply_failure
,reply_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))
到目前为止,这是我尝试过的事情,也是我考虑取代当前代码的事情。是Pythonic还是相反?