【问题标题】:Timeout handling while using run_in_executor and asyncio使用 run_in_executor 和 asyncio 时的超时处理
【发布时间】:2015-12-24 12:08:46
【问题描述】:

我正在使用 asyncio 运行一段这样的阻塞代码:

result = await loop.run_in_executor(None, long_running_function)

我的问题是:我可以对long_running_function 的执行施加超时吗?

基本上我不希望long_running_function 持续超过 2 秒,并且我无法在其中进行适当的超时处理,因为该函数来自第三方库。

【问题讨论】:

  • 您可以尝试将loop.run_in_executor() 包装在wait_for() 中,这需要一个超时参数。
  • 确实有效,谢谢!

标签: python python-asyncio python-3.5


【解决方案1】:

关于取消长时间运行的函数的警告:

虽然用asyncio.wait_for 调用包装由loop.run_in_executor 返回的Future 将允许事件循环x 秒后停止等待long_running_function,但它不会必须停止底层long_running_function。这是concurrent.futures 的缺点之一,据我所知,没有简单的方法可以取消concurrent.futures.Future

【讨论】:

  • 嗨 Jashandeep,您所说的“不一定会停止”是什么意思?你的意思是“不会停止”还是你能指出它不会停止的任何条件?
  • 顺便说一句,我们不是在谈论“asyncio.futures.Future”对象(而不是“concurrent.futures.Future”)吗?
  • 它不会立即停止;即该功能将运行完成。所以,如果那里有一个while True: ... 循环,它将永远不会停止。 --- asyncio 中的默认执行器是concurrent.futures.ThreadPoolExecutor,它又使用concurrent.futures.Futurerun_in_executor 调用 Executor.submit 并将返回的 concurrent.futures.Future 包装到 asyncio.Future 中,这样当一个完成时另一个完成。
  • 不,它不能。取消时,执行器不会将下一个任务安排到池中,但它不会停止已经执行的作业。从字面上看,没有办法使用 Python API 优雅地停止线程。黑客方法是存在的,但它们非常不可靠,我不推荐它们。
  • 我遇到了同样的问题,超时时间被提出,但阻塞功能继续运行,所以脚本只是挂起。我看到这些 cmets 已经 2 岁了,现在有解决方法吗?
【解决方案2】:

你可以使用asyncio.wait_for:

future = loop.run_in_executor(None, long_running_function)
result = await asyncio.wait_for(future, timeout, loop=loop)

【讨论】:

  • 完美,谢谢!达到超时时,表达式将抛出 asyncio.futures.TimeoutError
  • 警告:这是一个非常危险的答案。不要在生产中依赖它。它只会似乎做你想做的事:gist.github.com/coxley/5879f5ceecfbb4624bee23a6cef47510
  • @coxley 我尝试了您的示例,但无法复制您的错误。通过不打印“hell yeah”,它可以按预期工作。你运行的是什么python版本?我正在运行 python 3.6.8。也许你提到的问题已经解决了?
  • @chilicheech:我提出要点时是 Python 3.7,刚刚复制它时是 3.8.5。本质上,这不是要修复的错误。更多的是“陷阱”。 Asyncio 取消普通版不会影响执行器内部的工作。等待结果的未来按预期取消。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-12
  • 1970-01-01
  • 1970-01-01
  • 2016-09-08
  • 2016-08-06
  • 1970-01-01
相关资源
最近更新 更多