gpt4 book ai didi

python - 异步功能的可选同步接口(interface)

转载 作者:太空狗 更新时间:2023-10-30 02:41:19 24 4
gpt4 key购买 nike

我正在编写一个库,该库使用 Tornado Web 的 tornado.httpclient.AsyncHTTPClient 发出请求,这为我的代码提供了一个 async 接口(interface):

async def my_library_function():
return await ...

如果用户提供了一个 kwarg,我想让这个接口(interface)可选地串行化——类似于:serial=True。尽管您显然不能从没有 await 的普通函数中调用使用 async 关键字定义的函数。这将是理想的——尽管目前几乎可以肯定这在语言中是不可能的:

async def here_we_go():
result = await my_library_function()
result = my_library_function(serial=True)

我无法在网上找到任何有人为此提出好的解决方案。我不想在没有 awaits 的情况下重新实现基本相同的代码。

这是可以解决的问题还是需要语言的支持?


解决方案(尽管改用 Jesse 的 - 解释如下)

下面 Jesse 的解决方案几乎就是我要采用的解决方案。我最终确实通过使用装饰器获得了我最初想要的界面。像这样:

import asyncio
from functools import wraps


def serializable(f):
@wraps(f)
def wrapper(*args, asynchronous=False, **kwargs):
if asynchronous:
return f(*args, **kwargs)
else:
# Get pythons current execution thread and use that
loop = asyncio.get_event_loop()
return loop.run_until_complete(f(*args, **kwargs))
return wrapper

这给你这个界面:

result = await my_library_function(asynchronous=True)
result = my_library_function(asynchronous=False)

我理智地在 python 的异步邮件列表上检查了这个,我很幸运地得到了 Guido 的回应,他出于这个原因礼貌地拒绝了它:

Code smell -- being able to call the same function both asynchronously and synchronously is highly surprising. Also it violates the rule of thumb that the value of an argument shouldn't affect the return type.

很高兴知道它是可能的,但如果不被认为是一个很好的界面。 Guido 基本上建议了 Jesse 的答案,并在库中将包装函数作为辅助工具引入,而不是将其隐藏在装饰器中。

最佳答案

当你想同步调用这样的函数时,使用run_until_complete :

asyncio.get_event_loop().run_until_complete(here_we_go())

当然,如果你在代码中经常这样做,你应该想出这个语句的缩写,也许只是:

def sync(fn, *args, **kwargs):
return asyncio.get_event_loop().run_until_complete(fn(*args, **kwargs))

然后你可以这样做:

result = sync(here_we_go)

关于python - 异步功能的可选同步接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39778901/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com