即使使用 asyncio 和 aiohttp,方法也会等待请求响应

Posted

技术标签:

【中文标题】即使使用 asyncio 和 aiohttp,方法也会等待请求响应【英文标题】:Even using asyncio and aiohttp, methods wait for the request response 【发布时间】:2019-05-27 11:34:55 【问题描述】:

您好我有以下问题,我想执行 getlastItemFromGivenInterval 方法,让它在不等待请求响应的情况下短暂通过,并为 asyncio.sleep(60) 提供上下文以在 60 秒内再次执行整个过程时间框架。我得到的是在 getLastItemFromGivenInterval() 中等待请求结束。

import aiohttp
import asyncio

loop = asyncio.get_event_loop()
task = loop.create_task(main())
loop.run_forever()

async def main():
    async with aiohttp.ClientSession() as session:
        while True:
            await bc.getLastItemFromGivenInterval(session)
            await asyncio.sleep(60)

async def getLastItemFromGivenInterval(session):
    async with session.get(BinanceClient.base_endpoint + "/api/v1/time") as currentServerTime:
        currentServerTime = await currentServerTime.json()
        currentServerTime = currentServerTime['serverTime']

    async with session.get(url) as res:
        response = await res.json()
        array = []
        print(response)

        return response

getLastItemFromGivenInterval 放在单独的类中。 请给我一个提示,如何在 getLastItem...() 方法中实现不等待效果。

【问题讨论】:

我不是 100% 清楚你的问题,但似乎你的问题是 getlastItemFromGivenIntervalsleep 是同步的——如果你想同时运行它们,那么你可能希望等待 asyncio.gather -- await asyncio.gather(bc.getLastItemFromGivenInterval(session), asyncio.sleep(60)) 的结果,而不是单独等待每个项目。 @mgilson 我认为 OP 根本不想等待 getLastItemFromGivenIntervalgather() 会将睡眠与协程执行并行化,但如果协程最终花费很长时间,它仍然可能需要任意长的时间才能完成,而这是 OP 正在努力避免的事情。 asyncio.gather()中的第一个协程完成后如何获取结果? 【参考方案1】:

如果我理解正确,您希望在后台启动getLastItemFromGivenInterval,并且每 60 秒执行一次,无论完成需要多长时间。您可以将await 替换为create_task,然后永远不要等待生成的任务:

loop = asyncio.get_event_loop()
while True:
    # spawn the task in the background, and proceed
    loop.create_task(bc.getLastItemFromGivenInterval(session))
    # wait 60 seconds, allowing the above task (and other
    # tasks managed by the event loop) to run
    await asyncio.sleep(60)

您可能还希望确保不会累积需要很长时间才能完成或无限期挂起(例如由于网络故障)的任务:

loop = asyncio.get_event_loop()
while True:
    # asyncio.wait_for will cancel the task if it takes longer
    # than the specified duration
    loop.create_task(asyncio.wait_for(
        bc.getLastItemFromGivenInterval(session), 500))
    await asyncio.sleep(60)

【讨论】:

以上是关于即使使用 asyncio 和 aiohttp,方法也会等待请求响应的主要内容,如果未能解决你的问题,请参考以下文章

python 使用asyncio和aiohttp的scrapper的一个例子

python 使用asyncio和aiohttp的scrapper的一个例子

python asyncio 异步 I/O - 实现并发http请求(asyncio + aiohttp)

使用 aiohttp/asyncio 发出 100 万个请求 - 字面意思

如何使用 asyncio 和 aiohttp 异步通过 api 响应进行分页

asyncio和aiohttp