使用 run-in-executor 和 asyncio 以及 processPoolExecutor 处理超时

问题描述 投票:0回答:1

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

result = await loop.run_in_executor(pool, long_running_function)

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

我有什么选择?

  1. long_running_function?
    添加超时装饰器 https://pypi.org/project/timeout-decorator/
  2. 使用 Pebble https://pebble.readthedocs.io/en/latest/#pools-and-asyncio

哪个是最好的选择?

这个 q 非常接近 使用 run_in_executor 和 asyncio 时的超时处理,但没有报告解决方法。

已经过去几年了。 有解决方法吗?

python python-3.x asynchronous process python-asyncio
1个回答
0
投票

如果您无法控制目标长时间运行的代码,这会很棘手。但是,如果是 Python,则应该可以通过装饰来修改被调用的函数(即对另一个函数进行包装器调用) - 问题是,包装器无法在另一个函数内部添加超时检查代码。并且他们无法在超时后“杀死”它,即使它是在另一个线程中调用的。 但是,由于您正在其他进程中运行事物:与线程不同,子进程

可以从另一个进程中的外部线程中杀死。

但是你正在运行一个concurrent.futures兼容的执行器:简单地杀死目标进程就会杀死一个worker,而普通的stdlib的ProcessPoolExecutor如果你这样做的话就会被削弱——可能会导致整个执行器瘫痪。

如果 Pebble 的文档说他们的专业化之一正是允许在执行器中运行时超时 - 那么,这就是要走的路。

不过,不用再重复 Pebble,我要做的就是:有一个由执行器调用的目标控制包装函数:它将创建一个工作进程,并在需要时通过终止其工作进程来处理超时。 (它甚至可以处理通过队列发送的控制事件)。

或者,为了减少每个工作进程一个额外进程的开销,我可能会创建一个专门的执行器来处理超时,使用主进程异步循环本身(这可能是 Pebble 已经做的)。

但是,是的,为 ProcessPoolExecutor 任务设置“超时”可能是 Python 在未来版本中可以看到的一项增强功能 - 人们可以在该语言的官方想法主题中“投票”它,网址为

https://discuss.python.org/ c/想法/6

(在这里编写这样的控制代码是“可能的”,但考虑到与子进程相关的所有边缘情况将重新发明已经存在于 stdlib 和 Pebble 上的润滑良好的轮子,并且可能并不适合所有情况 - 尽管它肯定适用于简单的情况)

© www.soinside.com 2019 - 2024. All rights reserved.