监控并终止基于系统资源使用的Python脚本
怎样才能监控一个Python脚本使用的系统资源,并在资源使用超过某个预设值时终止它呢?我最关心的是内存使用情况。我并不是在问如何测量系统资源的使用情况,不过如果你有建议,我也乐意听。
举个简单的例子,假设我有一个函数,它用来找出小于某个大数字的质数,并根据某些条件把它们添加到一个列表中。我事先不知道会有多少个质数符合这个条件,所以我想确保在使用过多系统内存(比如说8GB)时能终止这个函数。我知道有方法可以监控Python对象的大小,但我不太清楚如何正确地监控这个列表的大小。我的想法是,在质数函数的循环中加入一个大小测试,如果超过8GB就退出,或者有没有什么“外部”的方法(这里的外部是指在循环之外,但仍然是Python脚本的一部分)来监控和退出。
我是在Mac上运行这个程序,但我问这个问题是想了解一般的情况。
2 个回答
resource.getrusage()
这个函数(特别是里面的 ru_idrss
)可以告诉你当前的 python
解释器使用了多少资源,你可以用这个信息来判断是否要停止处理。
在类Unix系统中,有一个很有用的“外部”方式来监控任何进程,那就是 ulimit 命令(你没有说明是否想在Windows上运行,Windows上没有 ulimit
,需要其他方法,但我不太了解这些;-)。
如果你想在自己的Python程序中进行这样的监控,只需修改相关的函数,检查每个要添加到列表中的对象的大小(并保持一个总和),当这个总和达到或超过某个阈值时就返回(你可以把这个阈值作为额外的参数传递给这个函数)。
编辑:提问者在评论中澄清了他们希望监控的地方是最糟糕的地方——在之前的段落中,我提到在进程外部监控很简单,在函数内部也很简单,但提问者想要的是“正好在中间”;-)。
最不糟糕的方法可能是使用“监视线程”——一个单独的守护线程,它在一个无限循环中,每隔 X
秒检查进程的资源消耗(例如在类Unix机器上可以用 resource.getrusage,如果是在Windows上,则需要其他方法),如果消耗超过了预设的限制,就尝试用 thread.interrupt_main 来终止主线程。当然,这种方法并不是万无一失的:周期 X
(在所有“轮询”的情况下都是如此)必须足够小,以便在此期间能够停止失控的进程,但又不能太小,以至于让进程变得非常缓慢。此外,主线程(唯一可以被这样中断的线程)可能会阻塞异常(在这种情况下,监视线程可能会尝试用“信号”来处理这个进程,信号的严重性逐渐增加,直到 SIGKILL
,这是一个永远无法被阻止或拦截的终止信号)。
所以,这种中间的方法比 ulimit
命令要复杂得多,更脆弱,也没有实质性的附加价值。但是,如果你想把监控放在“进程内部但在消耗资源的函数外部”,而且没有任何好处,工作量又大,还有我提到的其他缺点,那就是这样做的方法。