我最近在Python中运行异步函数,我想知道如何将同步函数转换为异步函数
例如,有一个通过谷歌api进行翻译的库。人们很可能想知道,如何异步翻译许多不同的单词。当然,你可以把它放在一个请求中,但是谷歌API会认为它是一个文本并相应地处理它,这将导致不正确的结果。
你怎么能把这个密码翻过来:
from pygoogletranslation import Translator
translator = Translator()
translations = []
words = ['partying', 'sightseeing', 'sleeping', 'catering']
for word in words:
translations.append(translator.translate(word, src='en', dest='es'))
print(translations)
为此:
from pygoogletranslation import Translator
import asyncio
translator = Translator()
translation_tasks = []
words = ['partying', 'sightseeing', 'sleeping', 'catering']
for word in words:
asyncio.create_task(translator.translate(word, src='en', dest='es'))
translations = asyncio.run(
asyncio.gather(translation_tasks, return_exceptions=True)
)
print(translations)
考虑到函数translate
没有内置的async
实现
正如在其他答案中提到的,调用阻塞函数对于ayncio是无用的。在这种情况下,我建议您使用^{} ,这是谷歌的官方翻译库
您可以在当前库中执行类似操作:
但这将以相同的方式运行任务,而不使用asyncio。asyncio的真正好处是,当某个东西挂起或等待时,它可以做其他事情。例如,在等待服务器的响应时,它可以发送另一个请求
Python如何知道某些工作正在等待完成?仅当函数(此处为coroutine)通过
await
关键字通知事件循环时。因此,您肯定需要使用本机支持异步操作的库。上面提到的google-cloud-translate
就是这样一个库。你可以做:您可以看到,这个客户机实际上将字符串列表作为输入,因此您可以直接在这里传递字符串列表。根据docs,这一限制是1024。所以,如果你的列表更大,你必须使用这个for循环
但是,您可能必须为此客户端设置凭据等,这超出了此问题的范围
您必须创建一个
async
函数,然后运行它。虽然如果translate没有内置的async
支持或正在阻塞,但是使用async
不会使它更快。按照注释中的建议,使用多线程/多处理可能更好要使函数异步,您需要使用
async def
来定义它,并将其更改为对任何可能阻塞的对象使用其他异步函数-例如,您将使用aiohttp
而不是requests
,等等。这项工作的重点是,该函数随后可以由事件循环与其他此类函数一起执行。每当异步函数需要等待某件事情时,如await
关键字所示,它将挂起到事件循环,并给其他函数一个执行的机会。事件循环将无缝地协调可能大量此类异步函数的并发执行。有关更多详细信息,请参见例如this answer如果您所依赖的关键阻塞函数没有异步实现,则可以使用^{} (或者,从Python 3.9开始,^{} )使其异步。但是,请注意,这些解决方案是“欺骗”的,因为它们在引擎盖下使用线程,因此它们不会提供通常由asyncio关联的好处,例如扩展到线程池中的线程数之外的能力,或者取消执行协程的能力
相关问题 更多 >
编程相关推荐