Geo*_*tov 8 python python-asyncio aiohttp
简单示例:我需要并行创建两个不相关的HTTP请求.最简单的方法是什么?我希望它是这样的:
async def do_the_job():
with aiohttp.ClientSession() as session:
coro_1 = session.get('http://httpbin.org/get')
coro_2 = session.get('http://httpbin.org/ip')
return combine_responses(await coro_1, await coro_2)
Run Code Online (Sandbox Code Playgroud)
换句话说,我想启动IO操作并等待其结果,以便它们有效地并行运行.这可以通过以下方式实现asyncio.gather:
async def do_the_job():
with aiohttp.ClientSession() as session:
coro_1 = session.get('http://example.com/get')
coro_2 = session.get('http://example.org/tp')
return combine_responses(*(await asyncio.gather(coro_1, coro_2)))
Run Code Online (Sandbox Code Playgroud)
接下来,我想要一些复杂的依赖结构.我希望在我拥有所有先决条件时开始操作,并在需要结果时获得结果.这里有助于asyncio.ensure_future分别从事件循环管理的协程中执行单独的任务:
async def do_the_job():
with aiohttp.ClientSession() as session:
fut_1 = asyncio.ensure_future(session.get('http://httpbin.org/ip'))
coro_2 = session.get('http://httpbin.org/get')
coro_3 = session.post('http://httpbin.org/post', data=(await coro_2)
coro_3_result = await coro_3
return combine_responses(await fut_1, coro_3_result)
Run Code Online (Sandbox Code Playgroud)
是不是在我的逻辑流程中使用协同程序实现并行非阻塞IO,我必须使用asyncio.ensure_future或者asyncio.gather(实际使用asyncio.ensure_future)?是否有一种不那么"冗长"的方式?
通常开发人员必须考虑协同应该成为单独的任务并使用上述功能来获得最佳性能,这是真的吗?
在事件循环中使用没有多个任务的协同程序是否有意义?
现实生活中的事件循环任务有多"重"?当然,它们比OS线程或进程"更轻".我应该在多大程度上争取尽可能少的此类任务?
我需要并行发出两个不相关的HTTP请求.最简单的方法是什么?
import asyncio
import aiohttp
async def request(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
return await resp.text()
async def main():
results = await asyncio.gather(
request('http://httpbin.org/delay/1'),
request('http://httpbin.org/delay/1'),
)
print(len(results))
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(main())
loop.run_until_complete(loop.shutdown_asyncgens())
finally:
loop.close()
Run Code Online (Sandbox Code Playgroud)
是的,您可以使用asyncio.gather或创建任务来实现并发asyncio.ensure_future.
接下来,我想要一些复杂的依赖结构?我希望在我拥有所有先决条件时开始操作,并在需要结果时获得结果.
虽然您提供的代码可以正常工作,但在不同的协同程序上拆分并发流程会更好,并再次使用asyncio.gather:
import asyncio
import aiohttp
async def request(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
return await resp.text()
async def get_ip():
return await request('http://httpbin.org/ip')
async def post_from_get():
async with aiohttp.ClientSession() as session:
async with session.get('http://httpbin.org/get') as resp:
get_res = await resp.text()
async with session.post('http://httpbin.org/post', data=get_res) as resp:
return await resp.text()
async def main():
results = await asyncio.gather(
get_ip(),
post_from_get(),
)
print(len(results))
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(main())
loop.run_until_complete(loop.shutdown_asyncgens())
finally:
loop.close()
Run Code Online (Sandbox Code Playgroud)
通常开发人员必须考虑协同应该成为单独的任务并使用上述功能来获得最佳性能,这是真的吗?
由于您使用asyncio,您可能希望同时运行一些作业以获得性能,对吧?asyncio.gather是一种说法 - "同时运行这些工作以更快地获得结果".
如果您不必考虑应该同时运行哪些作业以获得性能,那么使用纯同步代码可能没问题.
在事件循环中使用没有多个任务的协同程序是否有意义?
在您的代码中,如果您不想要它,则不必手动创建任务:此答案中的两个片段都不会使用asyncio.ensure_future.但是内部asyncio不断地使用任务(例如,正如您所指出的那样asyncio.gather使用任务本身).
现实生活中的事件循环任务有多"重"?当然,它们比OS线程或进程"更轻".我应该在多大程度上争取尽可能少的此类任务?
异步程序的主要瓶颈是(几乎总是)网络:您根本不必担心asyncio协同程序/任务的数量.
| 归档时间: |
|
| 查看次数: |
4370 次 |
| 最近记录: |