Python:ulimit和subprocess.call / subprocess.Popen很好用?

时间:2009-11-06 18:44:01

标签: python resources nice ulimit

我需要限制我使用subprocess.call从python进程生成的外部命令行应用程序所花费的时间和cpu,主要是因为有时生成的进程被卡住并将cpu的引脚设置为99%。

很好,ulimit似乎是合理的方法,但我不确定他们如何与子进程交互。

  • 限制看起来像:
    • 如果花费超过60秒,则终止该过程
    • 将其限制为cpu的20%
  • 我想将资源限制应用于子进程,而不是应用于生成子进程的python进程。

有没有办法将nice和ulimit应用于subprocess.call生成的进程?是否有更好的python-native替代品?

这是在linux(ubuntu)系统上。

3 个答案:

答案 0 :(得分:99)

将preexec_fn参数用于subprocess.Popen和资源模块。例如:

parent.py:

#!/usr/bin/env python

import os
import sys
import resource
import subprocess

def setlimits():
    # Set maximum CPU time to 1 second in child process, after fork() but before exec()
    print "Setting resource limit in child (pid %d)" % os.getpid()
    resource.setrlimit(resource.RLIMIT_CPU, (1, 1))

print "CPU limit of parent (pid %d)" % os.getpid(), resource.getrlimit(resource.RLIMIT_CPU)
p = subprocess.Popen(["./child.py"], preexec_fn=setlimits)
print "CPU limit of parent (pid %d) after startup of child" % os.getpid(), resource.getrlimit(resource.RLIMIT_CPU)
p.wait()
print "CPU limit of parent (pid %d) after child finished executing" % os.getpid(), resource.getrlimit(resource.RLIMIT_CPU)

child.py:

#!/usr/bin/env python

import os
import sys
import resource

print "CPU limit of child (pid %d)" % os.getpid(), resource.getrlimit(resource.RLIMIT_CPU)

parent.py 将分叉到一个新进程。在新进程中,它将调用setlimits(),然后执行 child.py 。这意味着资源将在子进程中受限,但不在父进程中。

运行程序时的输出:

./parent.py
CPU limit of parent (pid 17404) (-1, -1)
Setting resource limit in child (pid 17405)
CPU limit of parent (pid 17404) after startup of child (-1, -1)
CPU limit of child (pid 17405) (1, 1)
CPU limit of parent (pid 17404) after child finished executing (-1, -1)

在许多情况下,这比尝试使用ulimit更好,因为通过shell生成子进程并不总是一个好主意,特别是因为它经常导致丑陋的参数引用问题。

答案 1 :(得分:11)

您可以使用ulimitnice shell命令为子进程设置限制,如下所示:

import subprocess
subprocess.Popen('ulimit -t 60; nice -n 15 cpuhog', shell=True)

运行cpuhog,CPU时间限制为60秒,调整好15次。请注意,没有简单的方法可以设置20%的CPU限制。该过程将使用100%的CPU,除非另一个(不太好)的过程也需要CPU。

答案 2 :(得分:7)

Erik 让我很轻松,但他忘记了 Rich 指出的nice部分。我发现psutil包很好(双关语意)但遗憾的是不太便携。以下是我对这个问题的看法:

import os
import psutil
import resource
import subprocess

def preexec_fn():
    pid = os.getpid()
    ps = psutil.Process(pid)
    ps.set_nice(10)
    resource.setrlimit(resource.RLIMIT_CPU, (1, 1))

print "mother pid", os.getpid()
p = subprocess.Popen(["./cpuhog.sh"], preexec_fn=preexec_fn)
p.wait()
print "mother still alive with pid", os.getpid()

Ville 使用shell=True我过敏的地方。也许我只是在这里老了,脾气暴躁,但我尽量避免它!