Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 同时多个异步请求_Python_Python 3.x_Python Requests_Python Asyncio - Fatal编程技术网

Python 同时多个异步请求

Python 同时多个异步请求,python,python-3.x,python-requests,python-asyncio,Python,Python 3.x,Python Requests,Python Asyncio,我试图同时调用300个API调用,这样我最多可以在几秒钟内得到结果 我的伪代码如下所示: def function_1(): colors = ['yellow', 'green', 'blue', + ~300 other ones] loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) res = loop.run_until_complete(get_color_info(colors))

我试图同时调用300个API调用,这样我最多可以在几秒钟内得到结果

我的伪代码如下所示:

def function_1():
    colors = ['yellow', 'green', 'blue', + ~300 other ones]
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    res = loop.run_until_complete(get_color_info(colors))

async def get_color_info(colors):
    loop = asyncio.get_event_loop()
    responses = []
    for color in colors:
        print("getting color")
        url = "https://api.com/{}/".format(color)
        data = loop.run_in_executor(None, requests.get, url)
        r = await data
        responses.append(r.json())
    return responses
这样,我每隔一秒左右就会打印出
颜色
,而且代码会花费很长时间,所以我很确定它们不会同时运行。我做错了什么?

aiohttp
与本机协同程序(
async
/
wait
) 下面是一个典型的模式,它完成了您试图做的事情。(Python 3.7+)

一个主要的变化是,您需要从为同步IO构建的
请求
,移动到专门为使用
异步
/
等待
(本机协同程序)而构建的包:

这有两个不同的元素,一个是协同路由的异步方面,另一个是在指定任务容器(未来)时引入的并发性:

  • 您创建了一个协同程序
    get
    ,它使用
    await
    和两个可等待项:第一个是,第二个是。这是异步方面。等待这些IO绑定响应的目的是告诉事件循环,其他
    get()
    调用可以轮流运行相同的例程
  • 并发方面封装在
    wait asyncio.gather(*tasks)
    中。这将等待的
    get()
    调用映射到每个
    颜色。结果是返回值的聚合列表。请注意,此包装器将等待所有响应进入并调用
    .json()
    。或者,如果您希望在它们准备就绪时贪婪地处理它们,您可以循环:返回的每个未来对象表示剩余等待对象集中的最早结果
最后,请注意,Python 3.7中引入了一个高级“瓷器”函数。在早期版本中,您可以(大致)模拟它,如下所示:


限制请求
有许多方法可以限制并发率。例如,请参阅或。

好答案。我希望有一篇博文能简明扼要地解释这一点。关于这一主题的介绍性文章往往过时或完全不正确。您可能需要提到使用
信号量
来限制并发请求的数量,因为并发请求往往属于同一种模式。@user4815162342这是我最近写的一篇文章-感谢您的反馈和更正。当我尝试这一点时,它一直在做所有的事情(即拨打电话并立即得到响应),直到我将
asyncio.sleep(0)
放在
get
之后。有必要吗?
wait
关键字字面意思是等待结果。之后的任何指令仅在结果就绪后执行。同时进行工作需要同时运行多个协程,而不是让一个人做几件事。
import asyncio
import aiohttp  # pip install aiohttp aiodns


async def get(
    session: aiohttp.ClientSession,
    color: str,
    **kwargs
) -> dict:
    url = f"https://api.com/{color}/"
    print(f"Requesting {url}")
    resp = await session.request('GET', url=url, **kwargs)
    # Note that this may raise an exception for non-2xx responses
    # You can either handle that here, or pass the exception through
    data = await resp.json()
    print(f"Received data for {url}")
    return data


async def main(colors, **kwargs):
    # Asynchronous context manager.  Prefer this rather
    # than using a different session for each GET request
    async with aiohttp.ClientSession() as session:
        tasks = []
        for c in colors:
            tasks.append(get(session=session, color=c, **kwargs))
        # asyncio.gather() will wait on the entire task set to be
        # completed.  If you want to process results greedily as they come in,
        # loop over asyncio.as_completed()
        htmls = await asyncio.gather(*tasks, return_exceptions=True)
        return htmls


if __name__ == '__main__':
    colors = ['red', 'blue', 'green']  # ...
    # Either take colors from stdin or make some default here
    asyncio.run(main(colors))  # Python 3.7+
# The "full" versions makes a new event loop and calls
# loop.shutdown_asyncgens(), see link above
loop = asyncio.get_event_loop()
try:
    loop.run_until_complete(main(colors))
finally:
    loop.close()