首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >继续得到“asyncio.exceptions.TimeoutError”

继续得到“asyncio.exceptions.TimeoutError”
EN

Stack Overflow用户
提问于 2022-07-25 22:24:12
回答 1查看 240关注 0票数 4

下面的示例只将一个元素添加到事件循环中,并使用变量asins

当下面的asyncio.exceptions.TimeoutError参数为180个或更长时,我将得到一个asins错误。

如果我用这180个元素中的任何一个创建一个列表,我就会得到一个成功的响应,这告诉我下面的问题与API无关。

有人能告诉我怎么解决这个问题吗?谢谢!

代码语言:javascript
复制
import asyncio
import aiohttp
import sys
import pandas as pd

def create_params(asins_set):
    params = []
    for asin in asins_set:
        param = {
            'api_key': '...',
            'type': 'product',
            'amazon_domain': 'amazon.com',
            'asin': asin,
        }
        params.append(param)
    return params

if sys.version_info[0] == 3 and sys.version_info[1] >= 8 and sys.platform.startswith('win'):
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

# creates a list of tasks to add to the event loop at once
def get_tasks(session, params):
    tasks = []
    for param in params:
        tasks.append(session.get(
            'https://api.rainforestapi.com/request',
            params = param
        ))
    return tasks

results = []
async def get_suggested(params):
    async with aiohttp.ClientSession() as session:
        tasks = get_tasks(session, params)
        responses = await asyncio.gather(*tasks)
        for response in responses:
            results.append(await response.json())
        return results

def get_asin_titles(asins_set):
    params = create_params(asins_set)
    r = asyncio.run(get_suggested(params))
    asins_and_titles = dict()
    for result in r:
        if result['request_info']['success'] == True:
            asin = result['request_parameters']['asin']
            title = result['product']['title']
            asins_and_titles[asin] = title
    return asins_and_titles

asins = ['b07wp7q5bf']

final = get_asin_titles(asins)
print(final)
EN

回答 1

Stack Overflow用户

发布于 2022-07-28 18:44:36

问题可能在于同时进行的大量http连接。在这里,您尝试同时运行所有180个http请求。

代码语言:javascript
复制
responses = await asyncio.gather(*tasks)

因此,您需要限制同时运行http请求的数量。你可以用asyncio.Semaphore来做

信号量管理一个内部计数器,该计数器由每个and ()调用递减,并由每个release()调用递增。计数器永远不能低于零;当go ()发现它是零时,它会阻塞,直到某个任务调用some ()。

所以,您的代码将如下所示

代码语言:javascript
复制
...
sem = asyncio.Semaphore(10)

async def perform_request(session, param)
    async with sem:
        return await session.get(
            'https://api.rainforestapi.com/request',
            params = param
        )

def get_tasks(session, params):
    tasks = []
    for param in params:
        tasks.append(perform_request(session, param))
    return tasks

...

现在,如果您运行responses = await asyncio.gather(*tasks),一次只会运行10个并发http请求。

您可以使用数字10将解决方案调整为API速率。如果您使用sem = asyncio.Semaphore(1),所有请求将依次执行。

也许,对于这个API来说,它还是太快了。然后,您可以添加睡眠以减少RPS:

代码语言:javascript
复制
async def perform_request(session, param)
    async with sem:
        await asyncio.sleep(1)
        return await session.get(
            'https://api.rainforestapi.com/request',
            params = param
        )
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73115943

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档