gpt4 book ai didi

python - 增强同步软件 API 以允许异步消费

转载 作者:行者123 更新时间:2023-12-01 01:23:59 24 4
gpt4 key购买 nike

我有一个 Python 3.5+ 模块,提供了一个从远程 Web API 读取一些数据并返回它的函数。该函数依赖于包装函数,而包装函数又使用库 requests 进行 HTTP 调用。

这里是(故意省略所有数据验证逻辑和异常处理):

# module fetcher.py

import requests

# high-level module API
def read(some_params):
resp = requests.get('http://example.com', params=some_params)
return resp.json()

# wrapper for the actual remote API call
def get_data(some_params):
return call_web_api(some_params)

该模块当前已被多个客户端导入和使用。

截至今天,对 get_data 的调用本质上是同步的:这意味着无论谁使用函数 fetcher.read() 都知道这将阻塞线程该函数执行于。

我希望实现什么

我希望允许fetcher.read()以同步和异步方式(例如通过事件循环)两者运行。这是为了保持与使用该模块的现有调用者的兼容性,同时提供可能性利用非阻塞调用为确实想要异步调用函数的调用者提供更好的吞吐量。

这就是说,我的合法愿望是尽可能少地修改原始代码......

截至今天,我唯一知道的是 Requests 不支持开箱即用的异步操作,因此我应该切换到异步友好的 HTTP 客户端(例如 aiohttp)提供非阻塞行为

需要如何修改上述代码才能满足我的需求?这也让我问:是否有关于将同步软件 API 增强到异步上下文的最佳实践?强>

最佳答案

I want to allow the fetcher.read() to be run both in a synchronous and an asynchronous fashion (eg. via an event loop).

我认为通过同步和异步 API 都可以使用同一个函数是不可行的,因为使用模式非常不同。即使你能以某种方式让它工作,也很容易把事情搞砸,特别是考虑到 Python 的动态类型本质。 (例如,用户可能会意外忘记在异步代码中await他们的函数,并且同步代码将会启动,从而阻塞他们的事件循环。)

相反,我建议实际的 API 是异步的,并创建一个简单的同步包装器,仅使用 run_until_complete 调用入口点。大致如下:

# new module afetcher.py (or fetcher_async, or however you like it)

import aiohttp

# high-level module API
async def read(some_params):
async with aiohttp.request('GET', 'http://example.com', params=some_params) as resp:
return await resp.json()

# wrapper for the actual remote API call
async def get_data(some_params):
return call_web_api(some_params)

是的,您从使用 requests 切换到 aiohttp,但这种变化是机械性的,因为 API 在本质上非常相似。

同步模块的存在是为了向后兼容和方便,并且会简单地包装异步功能:

# module fetcher.py

import afetcher

def read(some_params):
loop = asyncio.get_event_loop()
return loop.run_until_complete(afetcher.read(some_params))

...

这种方法提供了 API 的同步和异步版本,没有代码重复,因为同步版本由简单的蹦床组成,可以使用适当的装饰器进一步压缩其定义。

异步 getter 模块应该有一个漂亮的短名称,这样用户就不会因为使用异步功能而感到受到惩罚。它应该易于使用,并且与同步 API 相比,它实际上提供了很多新功能,最显着的是低开销并行化和可靠取消。

推荐的路线是使用run_in_executor或类似的基于线程的工具在后台的线程池中运行请求。该实现并没有提供使用 asyncio 的实际好处,而是带来了所有成本。在这种情况下,最好继续提供同步 API,并让用户使用 concurrent.futures 或类似工具进行并行执行,这样他们至少知道自己正在使用线程。

关于python - 增强同步软件 API 以允许异步消费,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53521716/

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