如何优化这段代码?使用 python 的并发请求(并发库)

问题描述 投票:0回答:1

我正在 API (FastAPI) 中创建一个端点,该端点需要向具有非常大响应的外部 API 发送多个请求。外部 API 是分页的,我需要获取所有页面并在我的 API 中返回它们。通常,向外部 API 发出 15-25 个请求,在我当前的实现中可能需要长达 60 秒的时间。我想知道是否有更好的库(例如:asyncio)或不同的实现来潜在地减少我的端点中的响应时间。

这是我当前的(简化的)实现:

def load_url(url, page, parameters):
    parameters["page"] = page
    try:
        response = requests.get(url=url, params=parameters)
        return response
    except Exception as e:
        # handle exception

def get_response(total_page_number, url, parameters):
    items = []
    CONNECTIONS = 100
    with concurrent.futures.ThreadPoolExecutor(max_workers=CONNECTIONS) as executor:
        future_to_url = (
            executor.submit(load_url, url, page, parameters)
            for page in range(1, total_page_number + 1)
        )
        for future in concurrent.futures.as_completed(future_to_url):
            try:
                data = future.result()
            except Exception as exc:
                # handle exception
                print(exc)
            finally:
                items += data

    return items

最初我是一项一项地执行请求,这(可以预见)速度较慢。 (一对一的平均时间为 60 秒,当前解决方案的平均时间为 36 秒)想知道我是否做错了什么,并且非常感谢对此的一些指导。

(此代码是在堆栈溢出时从此线程获取并修改的,这是一个不同的用例(仅发送头请求))

python performance optimization concurrency python-requests
1个回答
0
投票

您可以尝试此代码并执行时间响应吗,因为我没有您运行的网址。这是一个 I/O 密集型任务,所以我使用

aiohttp

import asyncio
import aiohttp

async def load_url(client, url, header, page, parameters):
    parameters["page"] = page
    resp = await client.get(url, headers=header, params=parameters, timeout=300)
    if resp.status != 200:
        raise Exception(resp.text)
    data = await resp.json()
    return data

async def add_task(parameters, url, header, total_page_number):
    async with aiohttp.ClientSession(
        connector=aiohttp.TCPConnector(force_close=True, limit=50)
    ) as client:
        tasks = []
        for page in range(1, total_page_number + 1):
            tasks.append(
                asyncio.ensure_future(
                    load_url(client, url, header, page, parameters)
                )
            )
        list_result = await asyncio.gather(*tasks)
    return list_result

def get_response(parameters, url, header, total_page_number):
    return asyncio.run(add_task(parameters, url, header, total_page_number))
© www.soinside.com 2019 - 2024. All rights reserved.