学习 asyncio:异步运行一个有延迟的函数

Posted

技术标签:

【中文标题】学习 asyncio:异步运行一个有延迟的函数【英文标题】:Learning asyncio: Run a function with a delay asynchronously 【发布时间】:2020-11-02 22:42:47 【问题描述】:

我已经尝试学习 asyncio 几天了,但我无法让这个示例函数工作。我想加快发出几百个 HTTP 请求的速度,但我想从简单开始。我希望能够指定我想要多少个请求。当我一直在调整一些东西时,我遇到了很多不同的错误,但我无法让它工作。

这是我的代码:

import asyncio
import time

async def say():
  print("Started")
  await time.sleep(3) #something that takes a long time like an http request
  print("Finsihed")

loop = asyncio.get_event_loop()
asyncio.gather(say(),say(),say())
loop.run_forever()

我对此非常了解,我确信我在运行循环时做错了,但我不知道下一步该尝试什么。感谢您的帮助。

【问题讨论】:

您遇到了什么错误?您提供的第一步是对gather 的结果做一些事情,例如asyncio.run(asyncio.gather(...))(那么您甚至不需要loop)。 await time.sleep(3) 更改为await asyncio.sleep(3),您应该会看到预期的输出。 你不能等待任意的事情。 只能等待可以等待的东西。这方面的例子是用async def、任务和期货定义的东西。该页面上的示例都是这样。如果你想发出 HTTP 请求,你可以像那篇文章的作者那样使用 aiohttp。 @user4815162342 TIL。谢谢 【参考方案1】:

你的代码有几个问题:

您不能在 asyncio 代码中使用 time.sleep(),因为调用像 time.sleep() 这样的阻塞函数会阻塞整个事件循环。 你不能只调用asyncio.gather(),你必须等待它。 您可能应该使用更新和更强大的asyncio.run() API,而不是旧的loop.run_forever()

这是修复了这些问题的代码:

import asyncio

async def say():
    print("Started")
    await asyncio.sleep(3)
    print("Finsihed")

async def main():
    await asyncio.gather(say(), say(), say())

asyncio.run(main())

另请注意,您需要使用像 aiohttp 这样的异步感知库才能正确使用异步。

【讨论】:

非常感谢!我让它工作了。我最终使用 requests_async 但我认为相同的想法。我非常感谢您的彻底答复,但我还有一个问题。如果我想运行 say() x 次,如何创建一种添加 say() 来收集 x 次的方法?换句话说,我如何以编程方式定义我希望它运行多少次,然后将它多次添加到收集函数中,从而异步运行那么多次?

以上是关于学习 asyncio:异步运行一个有延迟的函数的主要内容,如果未能解决你的问题,请参考以下文章

Python并发编程之学习异步IO框架:asyncio 中篇

Python学习---Python的异步---asyncio模块(no-http)

Python 的 asyncio.gather() 似乎没有异步运行任务

异步IO框架:asyncio 中篇

asyncio,将普通函数包装为异步

Python学习---IO的异步[asyncio +aiohttp模块]